tazlito view tazlito @ rev 497

Use startup.nsh for uefi boot
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon May 14 15:57:23 2018 +0200 (2018-05-14)
parents da898b26deaf
children 5d84fadfd928
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-2018 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'
21 alias stat='busybox stat'
22 alias awk='busybox awk'
24 # Tazlito configuration variables to be shorter
25 # and to use words rather than numbers.
26 COMMAND="$1"
27 LIST_NAME="$2"
28 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
29 TMP_MNT="/media/tazlito-$$-$RANDOM"
30 TOP_DIR="$(pwd)"
31 INITRAMFS='rootfs.gz'
32 LOCALSTATE='/var/lib/tazpkg'
33 INSTALLED="$LOCALSTATE/installed"
34 CACHE_DIR='/var/cache/tazpkg'
35 MIRROR="$LOCALSTATE/mirror"
36 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
38 log='/var/log/tazlito.log'
39 if [ $(id -u) -eq 0 ]; then
40 newline > $log
41 fi
44 cleanup() {
45 if [ -d "$TMP_MNT" ]; then
46 umount $TMP_MNT
47 rmdir $TMP_MNT
48 rm -f /boot
49 fi
50 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
51 [ -d "$flv_dir" ] && rm -r "$flv_dir"
52 }
55 # Report error and finish work
57 die() {
58 emsg "<n>$(longline "$@")<n> " >&2
59 cleanup
60 exit 1
61 }
64 # Run Tazlito module
65 module() {
66 local mod="$1"; shift
67 /usr/libexec/tazlito/$mod $@
68 }
72 # Try to include config file, continue if command is gen-config or exit.
73 # The main config used by default is in /etc/tazlito.
74 # Specific distro config file can be put in a distro tree.
75 for i in /etc/tazlito "$TOP_DIR"; do
76 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
77 done
79 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
80 die 'Unable to find any configuration file.' \
81 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
83 . $CONFIG_FILE
85 # While Tazpkg is not used the default mirror URL file does not exist
86 # and user can't recharge the list of flavors.
87 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
89 # Set the rootfs and rootcd path with $DISTRO
90 # configuration variable.
91 ROOTFS="$DISTRO/rootfs"
92 ROOTCD="$DISTRO/rootcd"
97 #####################
98 # Tazlito functions #
99 #####################
102 # Print the usage.
104 usage () {
105 [ $(basename $0) == 'tazlito' ] && cat <<EOT
107 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
109 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
111 $(boldify "Commands:")
112 EOT
113 optlist "\
114 usage Print this short usage.
115 stats View Tazlito and distro configuration statistics.
116 list-addfiles Simple list of additional files in the rootfs.
117 gen-config Generate a new configuration file for a distro.
118 configure Configure the main config file or a specific tazlito.conf.
119 gen-iso Generate a new ISO from a distro tree.
120 gen-initiso Generate a new initramfs and ISO from the distro tree.
121 list-flavors List all flavors available on the mirror.
122 gen-flavor Generate a new Live CD description.
123 gen-liveflavor Generate a Live CD description from current system.
124 show-flavor Show Live CD description.
125 get-flavor Get a flavor's list of packages (--noup to skip update).
126 upgrade-flavor Update package list to the latest available versions.
127 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
128 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
129 iso2flavor Create a flavor file from a SliTaz ISO image.
130 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
131 gen-distro Generate a Live distro and ISO from a list of packages.
132 clean-distro Remove all files generated by gen-distro.
133 check-distro Help to check if distro is ready to release.
134 writeiso Use running system to generate a bootable ISO (with /home).
135 merge Merge multiple rootfs into one ISO.
136 deduplicate Deduplicate files in a tree.
137 repack Recompress rootfs into ISO with maximum ratio.
138 build-loram Generate a Live CD for low-RAM systems.
139 emu-iso Emulate an ISO image with QEMU.
140 burn-iso Burn ISO image to a CD-ROM using Wodim.
141 "
142 }
145 yesorno() {
146 local answer
147 echo -n "$1 (y=yes, n=no) [$2] " >&2
148 case "$DEFAULT_ANSWER" in
149 Y|y) answer="y";;
150 N|n) answer="n";;
151 *)
152 read -t 30 answer
153 [ -z "$answer" ] && answer="$2"
154 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
155 ;;
156 esac
157 echo "$answer"
158 }
161 field() {
162 grep "^$1" "$2" | \
163 case "$1" in
164 Desc*) sed 's|^.*: *||';;
165 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
166 esac
167 }
170 todomsg() {
171 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
172 }
175 # Download a file from this mirror
177 download_from() {
178 local i mirrors="$1"
179 shift
180 for i in $mirrors; do
181 case "$i" in
182 http://*|ftp://*|https://*)
183 wget -c $i$@ && break;;
184 *)
185 cp $i/$1 . && break;;
186 esac
187 done
188 }
191 # Download a file trying all mirrors
193 download() {
194 local i
195 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
196 download_from "$i" "$@" && break
197 done
198 }
201 # Execute hooks provided by some packages
203 genisohooks() {
204 local here="$(pwd)"
205 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
206 cd $ROOTFS
207 . $i $ROOTCD
208 done
209 cd "$here"
210 }
213 # Echo the package name if the tazpkg is already installed
215 installed_package_name() {
216 local tazpkg="$1" package VERSION EXTRAVERSION
218 # Try to find package name and version to be able
219 # to repack it from installation
220 # A dash (-) can exist in name *and* in version
221 package=${tazpkg%-*}
222 i=$package
223 while true; do
224 unset VERSION EXTRAVERSION
225 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
226 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
227 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
228 echo $i
229 break
230 fi
231 case "$i" in
232 *-*);;
233 *) break;;
234 esac
235 i=${i%-*}
236 done
237 }
240 # Check for the rootfs tree.
242 check_rootfs() {
243 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
244 }
247 # Check for the boot dir into the root CD tree.
249 verify_rootcd() {
250 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
251 }
253 set32() {
254 for i in $(seq 0 8 $((${4:-32}-8))); do
255 printf '\\\\x%02X' $((($2 >> $i) & 255))
256 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
257 }
259 set64() {
260 for i in $(seq 0 8 24 ; seq 24 -8 0); do
261 printf '\\\\x%02X' $((($2 >> $i) & 255))
262 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
263 }
266 first_block() {
267 busybox stat -m "$1" | sed q
268 }
272 # Force size and location in the 2nd eltorito boot file (/boot/isolinux/efi.img)
274 fix_efi_boot_img_size() {
275 local n=$3
276 [ $n -gt 65535 ] && n=65535
277 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
278 set32 $((0x1C+2048*$4)) $(($4*4)) $1
279 }
282 # Force the size for the /boot/isolinux/efi.img file
284 fix_efi_img_size() {
285 local e=$((0x809C))
286 for i in BOOT ISOLINUX EFI.IMG ; do
287 local sz=$(get $(($e+10)) "$2" 4)
288 e=$(($(get $(($e+2)) "$2" 4) * 2048))
289 while [ $sz -gt 0 ]; do
290 local len=$(get $e "$2")
291 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
292 2>/dev/null)" == "$i" ] && continue 2
293 [ $len -eq 0 ] && break
294 sz=$(($sz-$len))
295 e=$(($e+$len))
296 done
297 return # not found
298 done
299 set64 $(($e+10)) $1 "$2"
300 }
303 # create /boot/isolinux/efi.img to share EFI files with the iso image
305 fixup_uefi_part() {
306 [ -s $2/boot/isolinux/efi.img ] || return
307 local n=$(get 19 "$2/boot/isolinux/efi.img")
308 [ $n -eq 0 ] && n=$(get 32 "$2/boot/isolinux/efi.img" 4)
309 efiblock=$(first_block "$2/boot/isolinux/efi.img")
310 fix_efi_img_size $(($n*512)) $1
311 fix_efi_boot_img_size $1 $2 $n $efiblock
313 # Build file list tree
314 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
315 resv=$(get 14 "$2/boot/isolinux/efi.img")
316 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
317 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead=4 }
318 {
319 if (skiphead!=0) {
320 if ($1=="*") skiphead--
321 next
322 }
323 if (skipdot!=0) {
324 if (skipdot==2) up[cur]=$13 $12
325 else cur=$13 $12
326 skipdot=0
327 next
328 }
329 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
330 if ($3=="2e") skipdot=2
331 else skipdot=1
332 next
333 }
334 if (gotname!=0) {
335 path=""
336 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
337 if (gotname==2) dir[$13 $12]=name
338 else print $1 " " $13 $12 " " path name
339 gotname=0
340 name=""
341 next
342 }
343 if (s!="") {
344 if (eos==0)
345 for (i=2;i<18;i+=2) {
346 if (i==12) i+=2
347 if ($i=="00") break
348 s=s substr($0,i+60,1)
349 }
350 name=s name
351 s=""
352 eos=0
353 next
354 }
355 if ($13=="0f") {
356 s=""
357 for (i=3;i<16;i+=2) {
358 if (i==13) i+=3
359 if ($i=="00") { eos=1; break }
360 s=s substr($0,i+60,1)
361 }
362 next
363 }
364 if ($13=="10") {
365 name=name "/"
366 gotname=2
367 next
368 }
369 if ($13=="20") {
370 gotname=1
371 next
372 }
373 }
374 ' | ( while read offset cluster file; do
375 cluster=$(($(first_block "$2/$file")-$basecluster))
376 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
377 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
378 done
380 # Update fat12 or fat16
381 get 57 "$2/boot/isolinux/efi.img"
382 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
383 od -An -t u1 -w1 -v
384 ) | awk '
385 {
386 if (state==0) {
387 if ($2=="") {
388 if ($1==12849) fat=12
389 else fat=16
390 state++
391 }
392 else {
393 for (i=1;i<$2;i++) c[$1+i]=$1+i
394 c[$1+$2]=65535
395 }
396 next
397 }
398 if (state==1) {
399 prev=$1
400 state++
401 next
402 }
403 if (state==2) {
404 if (fat==12) {
405 n=($1%16)*256+prev
406 if (n!=0) c[pos+1]=n
407 pos++
408 prev=$1/16
409 state++
410 next
411 }
412 n=$1*256+prev
413 }
414 else if (state==3) {
415 n=$1*16+prev
416 }
417 if (n!=0) c[pos+1]=n
418 pos++
419 state=1
420 }
421 END {
422 for (i=1;i<=pos;i+=2) {
423 if (c[i]=="") c[i]=0
424 if (c[i+1]=="") c[i+1]=0
425 if (fat==12) printf "0 %02X %02X %02X |\n",c[i]%256,(c[i+1]%16)*16+(c[i]/256)%256,(c[i+1]/16)%256
426 else printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,c[i+1]%256,(c[i+1]/256)%256
427 }
428 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
429 conv=notrunc bs=512 > /dev/null 2>&1
430 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
431 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
433 # Cleanup cache
434 umount $2
435 mount -o loop,ro $1 $2
436 }
439 # allocate efi.img stub to share EFI files in the EFI boot partition
441 alloc_uefi_part() {
442 local basedir=$(dirname "$1")/..
443 local fclust=$({
444 [ -d $basedir/efi ] &&
445 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
446 while [ -s "$1" ]; do
447 local efifile
448 case "$1" in
449 *taz) efifile=bootia32.efi ;;
450 *taz64) efifile=bootx64.efi ;;
451 esac
452 if [ ! -s $basedir/efi/boot/$efifile ] &&
453 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
454 mkdir -p $basedir/efi/boot 2> /dev/null
455 for i in "$1" $basedir/boot/rootfs* ; do
456 ln "$i" $basedir/efi/boot/
457 stat -c "%s %n" "$i"
458 done 2> /dev/null
459 cat >> $basedir/efi/boot/startup.nsh <<EOT
460 FS0:\\EFI\\BOOT\\$(basename $1) rw root=0x100$( ( cd $basedir/efi/boot ; \
461 ls -r rootfs*gz ) | while read f ; do [ "$efifile" == "bootx64.efi" -a \
462 -s $basedir/efi/boot/${f}64 ] && f=${f}64; echo -n " initrd=/EFI/BOOT/$f";done)
463 EOT
464 fi
465 shift
466 done; } | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
467 [ ${fclust:-0} -eq 0 ] && return
468 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
469 BEGIN {
470 FS="/"
471 }
472 NF > 1 {
473 d[NF $NF]+=2
474 d[NF-1 $(NF-1)]+=($NF+25)/13
475 }
476 END {
477 for (i in d)
478 n+=int((d[i]+63)/64)
479 print n
480 }')
481 local clusters=$(($fclust+$dclust))
482 if [ $clusters -lt 4085 ]; then
483 fsect=$(((($clusters+2)*3+1023)/1024))
484 ftype="31 32"
485 fhead="F8 FF FF"
486 else
487 fsect=$((($clusters+2+255)/256))
488 ftype="31 36"
489 fhead="F8 FF FF FF"
490 fi
491 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
492 fsz="$(printf "%02X %02X" $(($fsect%256)) $((($fsect>>8)%256)))"
493 # reserved + fat*2 + root dir + dirs
494 count=$((($rsect + $fsect*2)/4 + 2 + $dclust ))
495 s=$((($count+$fclust)*4))
496 if [ $s -gt 65535 ]; then
497 size="00 00"
498 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
499 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
500 else
501 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
502 size32="00 00 00 00"
503 fi
504 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
505 count=$s 2> /dev/null
507 # Create boot sector
508 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
509 seek=510 bs=1 conv=notrunc 2> /dev/null
510 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
511 conv=notrunc 2> /dev/null
512 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
513 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
514 0 $size32 80 00 29 00 00 00 00 4e 4f 20 4e 41 |
515 0 4d 45 20 20 20 20 46 41 54 $ftype 20 20 20 cd 18 |
516 0 cd 19 eb fa |
517 EOT
519 # Create fats
520 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
521 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
522 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
523 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
525 mkdir -p /tmp/mnt$$
526 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
527 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
528 ( cd /tmp/mnt$$ ; cpio -idmu )
529 sync
530 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
531 skip=$rsect bs=512 count=$fsect 2> /dev/null
532 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
533 ( cd /tmp/mnt$$ ; cpio -idmu )
534 umount /tmp/mnt$$
535 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
536 seek=$rsect bs=512 conv=notrunc 2> /dev/null
537 rm /tmp/fat$$
538 rmdir /tmp/mnt$$
540 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
541 seek=$count 2> /dev/null
542 }
545 # isolinux.conf doesn't know the kernel version.
546 # We name the kernel image 'bzImage'.
547 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
549 make_bzImage_hardlink() {
550 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
551 rm -f ${1:-.}/bzImage 2>/dev/null
552 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
553 fi
554 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
555 rm -f ${1:-.}/bzImage64 2> /dev/null
556 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
557 fi
558 }
561 create_iso() {
562 cd $2
563 deduplicate
565 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
566 make_bzImage_hardlink $2/boot
567 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
569 cat > /tmp/cdsort$$ <<EOT
570 $PWD/boot/isolinux 100
571 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
572 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
573 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
574 $PWD/boot/isolinux/efi.img 300
575 $PWD/boot/isolinux/isolinux.bin 399
576 $PWD/boot/isolinux/boot.cat 400
577 EOT
579 action 'Computing md5...'
580 touch boot/isolinux/boot.cat
581 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
582 sort -k 2 > md5sum
583 status
585 cd - >/dev/null
586 title 'Generating ISO image'
588 _ 'Generating %s' "$1"
589 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
590 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
591 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
592 -no-emul-boot -boot-load-size 4 -boot-info-table \
593 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
594 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
595 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
596 -A "tazlito $VERSION/$(genisoimage --version)" \
597 -copyright README -P "www.slitaz.org" -no-pad $2
598 rm -f /tmp/cdsort$$
599 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
601 mkdir /tmp/mnt$$
602 mount -o loop,ro $1 /tmp/mnt$$
603 fixup_uefi_part $1 /tmp/mnt$$
604 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
605 ${uefi:+boot/isolinux/efi.img} ; do
606 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
607 done
608 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
609 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
610 umount -d /tmp/mnt$$
611 rmdir /tmp/mnt$$
613 if [ -s '/etc/tazlito/info' ]; then
614 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
615 action 'Storing ISO info...'
616 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
617 status
618 fi
619 fi
621 if [ -x '/usr/bin/isohybrid' ]; then
622 action 'Creating hybrid ISO...'
623 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
624 status
625 fi
627 if [ -x '/usr/bin/iso2exe' ]; then
628 echo 'Creating EXE header...'
629 /usr/bin/iso2exe $1 2>/dev/null
630 fi
631 }
634 # Generate a new ISO image using isolinux.
636 gen_livecd_isolinux() {
637 # Some packages may want to alter iso
638 genisohooks iso
639 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
641 # Set date for boot msg.
642 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
643 DATE=$(date +%Y%m%d)
644 action 'Setting build date to: %s...' "$DATE"
645 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
646 status
647 fi
649 cd $DISTRO
650 create_iso $ISO_NAME.iso $ROOTCD
652 action 'Creating the ISO md5sum...'
653 md5sum $ISO_NAME.iso > $ISO_NAME.md5
654 status
656 separator
657 # Some packages may want to alter final iso
658 genisohooks final
659 }
662 lzma_history_bits() {
663 #
664 # This generates an ISO which boots with Qemu but gives
665 # rootfs errors in frugal or liveUSB mode.
666 #
667 # local n
668 # local sz
669 # n=20 # 1Mb
670 # sz=$(du -sk $1 | cut -f1)
671 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
672 # n=$(( $n + 1 ))
673 # sz=$(( $sz / 2 ))
674 # done
675 # echo $n
676 echo ${LZMA_HISTORY_BITS:-24}
677 }
680 lzma_switches() {
681 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
682 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
683 }
686 lzma_set_size() {
687 # Update size field for lzma'd file packed using -si switch
688 return # Need to fix kernel code?
690 local n i
691 n=$(unlzma < $1 | wc -c)
692 for i in $(seq 1 8); do
693 printf '\\\\x%02X' $(($n & 255))
694 n=$(($n >> 8))
695 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
696 }
699 align_to_32bits() {
700 local size=$(stat -c %s ${1:-/dev/null})
701 [ $((${size:-0} & 3)) -ne 0 ] &&
702 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
703 }
706 dogzip() {
707 gzip -9 > $1
708 [ -x /usr/bin/advdef ] && advdef -qz4 $1
709 }
712 # Pack rootfs
714 pack_rootfs() {
715 ( cd $1; find . -print | cpio -o -H newc ) | \
716 case "$COMPRESSION" in
717 none)
718 _ 'Creating %s without compression...' 'initramfs'
719 cat > $2
720 ;;
721 gzip)
722 _ 'Creating %s with gzip compression...' 'initramfs'
723 dogzip $2
724 ;;
725 *)
726 _ 'Creating %s with lzma compression...' 'initramfs'
727 lzma e -si -so $(lzma_switches $1) > $2
728 lzma_set_size $2
729 ;;
730 esac
731 align_to_32bits $2
732 echo 1 > /tmp/rootfs
733 }
736 # Compression functions for writeiso.
738 write_initramfs() {
739 case "$COMPRESSION" in
740 lzma)
741 _n 'Creating %s with lzma compression...' "$INITRAMFS"
742 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
743 align='y'
744 lzma_set_size "/$INITRAMFS"
745 ;;
746 gzip)
747 _ 'Creating %s with gzip compression...' "$INITRAMFS"
748 cpio -o -H newc | dogzip "/$INITRAMFS"
749 ;;
750 *)
751 # align='y'
752 _ 'Creating %s without compression...' "$INITRAMFS"
753 cpio -o -H newc > "/$INITRAMFS"
754 ;;
755 esac < /tmp/list
756 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
757 echo 1 > /tmp/rootfs
758 }
761 # Deduplicate files (MUST be on the same filesystem).
763 deduplicate() {
764 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
765 (
766 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
767 while read attr inode link file; do
768 [ -L "$file" ] && continue
769 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
770 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
771 rm -f "$file"
772 if ln "$old_file" "$file" 2>/dev/null; then
773 inode="$old_inode"
774 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
775 save="$(($save+(${attr%%-*}+512)/1024))"
776 else
777 cp -a "$old_file" "$file"
778 fi
779 fi
780 fi
781 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
782 done
783 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
784 )
786 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
787 (
788 old_attr=""; hardlinks=0;
789 while read attr inode link file; do
790 attr="${attr/-TARGET-/-$(readlink $file)}"
791 if [ "$attr" == "$old_attr" ]; then
792 if [ "$inode" != "$old_inode" ]; then
793 rm -f "$file"
794 if ln "$old_file" "$file" 2>/dev/null; then
795 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
796 else
797 cp -a "$old_file" "$file"
798 fi
799 fi
800 else
801 old_file="$file"
802 old_attr="$attr"
803 old_inode="$inode"
804 fi
805 done
806 _ '%s duplicate symlinks.' "$hardlinks"
807 )
808 }
811 # Generate a new initramfs from the root filesystem.
813 gen_initramfs() {
814 # Just in case CTRL+c
815 rm -f $DISTRO/gen
817 # Some packages may want to alter rootfs
818 genisohooks rootfs
819 cd $1
821 # Normalize file time
822 find $1 -newer $1 -exec touch -hr $1 {} \;
824 # Link duplicate files
825 deduplicate
827 # Use lzma if installed. Display rootfs size in realtime.
828 rm -f /tmp/rootfs 2>/dev/null
829 pack_rootfs . $DISTRO/$(basename $1).gz &
830 sleep 2
831 echo -en "\nFilesystem size:"
832 while [ ! -f /tmp/rootfs ]; do
833 sleep 1
834 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
835 done
836 echo -e "\n"
837 rm -f /tmp/rootfs
838 cd $DISTRO
839 mv $(basename $1).gz $ROOTCD/boot
840 }
843 distro_sizes() {
844 if [ -n "$start_time" ]; then
845 time=$(($(date +%s) - $start_time))
846 sec=$time
847 div=$(( ($time + 30) / 60))
848 [ "$div" -ne 0 ] && min="~ ${div}m"
849 _ 'Build time : %ss %s' "$sec" "$min"
850 fi
851 cat <<EOT
852 Build date : $(date +%Y%m%d)
853 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
854 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
855 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
856 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
857 EOT
858 footer "Image is ready: $ISO_NAME.iso"
859 }
862 # Print ISO and rootfs size.
864 distro_stats() {
865 title 'Distro statistics: %s' "$DISTRO"
866 distro_sizes
867 }
870 # Create an empty configuration file.
872 empty_config_file() {
873 cat >> tazlito.conf <<"EOF"
874 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
875 #
877 # Name of the ISO image to generate.
878 ISO_NAME=""
880 # ISO image volume name.
881 VOLUM_NAME="SliTaz"
883 # Name of the preparer.
884 PREPARED="$USER"
886 # Path to the packages repository and the packages.list.
887 PACKAGES_REPOSITORY=""
889 # Path to the distro tree to gen-distro from a list of packages.
890 DISTRO=""
892 # Path to the directory containing additional files
893 # to copy into the rootfs and rootcd of the LiveCD.
894 ADDFILES="$DISTRO/addfiles"
896 # Default answer for binary question (Y or N)
897 DEFAULT_ANSWER="ASK"
899 # Compression utility (lzma, gzip or none)
900 COMPRESSION="lzma"
901 EOF
902 }
905 # Extract rootfs.gz somewhere
907 extract_rootfs() {
908 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
909 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
910 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
911 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
912 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
913 }
916 # Extract flavor file to temp directory
918 extract_flavor() {
919 # Input: $1 - flavor name to extract;
920 # $2 = absent/empty: just extract 'outer layer'
921 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
922 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
923 # Output: temp dir path where flavor was extracted
924 local f="$1.flavor" from to infos="$1.desc"
925 [ -f "$f" ] || die "File '$f' not found"
926 local dir="$(mktemp -d)"
927 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
929 if [ -n "$2" ]; then
930 cd $dir
932 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
934 for i in rootcd rootfs; do
935 [ -f "$1.$i" ] || continue
936 mkdir "$i"
937 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
938 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
939 rm "$1.$i"
940 done
941 touch -t 197001010100.00 $1.*
942 # Info to be stored inside ISO
943 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
944 rm $1.list*
946 # Renames
947 while read from to; do
948 [ -f "$from" ] || continue
949 mv "$from" "$to"
950 done <<EOT
951 $1.nonfree non-free.list
952 $1.pkglist packages.list
953 $1-distro.sh distro.sh
954 $1.receipt receipt
955 $1.mirrors mirrors
956 $1.desc description
957 EOT
958 fi
960 echo $dir
961 }
964 # Pack flavor file from temp directory
966 pack_flavor() {
967 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
968 }
971 # Remove duplicate files
973 files_match() {
974 if [ -d "$1" ]; then
975 return 1
977 elif [ -L "$1" ] && [ -L "$2" ]; then
978 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
980 elif [ -f "$1" ] && [ -f "$2" ]; then
981 cmp -s "$1" "$2" && return 0
983 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
984 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
985 return 0
987 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
988 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
989 return 0
991 fi 2> /dev/null
992 return 1
993 }
995 remove_with_path() {
996 dir="$(dirname $1)"
997 rm -f "$1"
998 while rmdir "$dir" 2> /dev/null; do
999 dir="$(dirname $dir)"
1000 done
1003 mergefs() {
1004 # Note, many packages have files with spaces in the name
1005 IFS=$'\n'
1007 local size1=$(du -hs "$1" | awk '{ print $1 }')
1008 local size2=$(du -hs "$2" | awk '{ print $1 }')
1009 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1011 # merge symlinks files and devices
1012 ( cd "$1"; find ) | \
1013 while read file; do
1014 files_match "$1/$file" "$2/$file" "$file" &&
1015 remove_with_path "$2/$file"
1016 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1017 done
1019 unset IFS
1020 status
1024 cleanup_merge() {
1025 rm -rf $TMP_DIR
1026 exit 1
1030 # Update isolinux config files for multiple rootfs
1032 update_bootconfig() {
1033 local files
1034 action 'Updating boot config files...'
1035 files="$(grep -l 'include common' $1/*.cfg)"
1036 for file in $files; do
1037 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1038 if (/label/) label=$0;
1039 else if (/kernel/) kernel=$0;
1040 else if (/append/) {
1041 i=index($0,"rootfs.gz");
1042 append=substr($0,i+9);
1044 else if (/include/) {
1045 for (i = 1; i <= n; i++) {
1046 print label i
1047 print kernel;
1048 initrd="initrd=/boot/rootfs" n ".gz"
1049 for (j = n - 1; j >= i; j--) {
1050 initrd=initrd ",/boot/rootfs" j ".gz";
1052 printf "\tappend %s%s\n",initrd,append;
1053 print "";
1055 print;
1057 else print;
1058 }' < $file > $file.$$
1059 mv -f $file.$$ $file
1060 done
1061 sel="$(echo $2 | awk '{
1062 for (i=1; i<=NF; i++)
1063 if (i % 2 == 0) printf " slitaz%d", i/2
1064 else printf " %s", $i
1065 }')"
1067 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1069 label slitaz
1070 kernel /boot/isolinux/ifmem.c32
1071 append$sel noram
1073 label noram
1074 config noram.cfg
1076 EOT
1078 # Update vesamenu
1079 if [ -s "$1/isolinux.cfg" ]; then
1080 files="$files $1/isolinux.cfg"
1081 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1082 BEGIN {
1083 kernel = " COM32 c32box.c32"
1086 if (/ROWS/) print "MENU ROWS " n+$3;
1087 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1088 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1089 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1090 else if (/VSHIFT/) {
1091 x = $3-n;
1092 if (x < 0) x = 0;
1093 print "MENU VSHIFT " x;
1095 else if (/rootfs.gz/) {
1096 linux = "";
1097 if (/bzImage/) linux = "linux /boot/bzImage ";
1098 i = index($0, "rootfs.gz");
1099 append = substr($0, i+9);
1100 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1101 printf "\tappend%s noram\n", sel;
1102 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1103 for (i = 1; i <= n; i++) {
1104 print "LABEL slitaz" i
1105 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1106 printf "%s\n", kernel;
1107 initrd = "initrd=/boot/rootfs" n ".gz"
1108 for (j = n - 1; j >= i; j--) {
1109 initrd = initrd ",/boot/rootfs" j ".gz";
1111 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1114 else if (/bzImage/) kernel = $0;
1115 else print;
1116 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1117 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1118 fi
1120 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1121 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1122 cat > $1/noram.cfg <<EOT
1123 implicit 0
1124 prompt 1
1125 timeout 80
1126 $(grep '^F[0-9]' $1/isolinux.cfg)
1128 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1129 say Not enough RAM to boot slitaz. Trying hacker mode...
1130 default hacker
1131 label hacker
1132 KERNEL /boot/bzImage
1133 append rw root=/dev/null vga=normal
1135 label reboot
1136 EOT
1138 if [ -s $1/c32box.c32 ]; then
1139 cat >> $1/noram.cfg <<EOT
1140 COM32 c32box.c32
1141 append reboot
1143 label poweroff
1144 COM32 c32box.c32
1145 append poweroff
1147 EOT
1148 else
1149 echo " com32 reboot.c32" >> $1/noram.cfg
1150 fi
1152 # Restore real label names
1153 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1154 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1155 while read pat; do
1156 sed -i "s/slitaz$pat/" $files
1157 done
1158 status
1162 # Uncompress rootfs or module to stdout
1164 uncompress() {
1165 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1166 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1170 # Install a missing package
1172 install_package() {
1173 if [ -z "$2" ]; then
1174 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1175 else
1176 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1177 fi
1178 case "$answer" in
1179 y)
1180 # We don't want package on host cache.
1181 action 'Getting and installing package: %s' "$1"
1182 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1183 status ;;
1184 *)
1185 return 1 ;;
1186 esac
1190 # Check iso for loram transformation
1192 check_iso_for_loram() {
1193 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1194 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1198 # Build initial rootfs for loram ISO ram/cdrom/http
1200 build_initfs() {
1201 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1202 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1203 mirror3.slitaz.org mirror.slitaz.org"
1204 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1205 [ -z "$version" ] && die "Can't find the kernel version." \
1206 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1208 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1209 need_lib=false
1210 for i in bin dev run mnt proc tmp sys lib/modules; do
1211 mkdir -p $TMP_DIR/initfs/$i
1212 done
1213 ln -s bin $TMP_DIR/initfs/sbin
1214 ln -s . $TMP_DIR/initfs/usr
1215 for aufs in aufs overlayfs; do
1216 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1217 install_package linux-$aufs $version && break
1218 install_package $aufs $version && break
1219 done || return 1
1220 [ -s /init ] || install_package slitaz-boot-scripts
1221 cp /init $TMP_DIR/initfs/
1222 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1223 $TMP_DIR/initfs/lib/modules
1224 if [ "$1" == 'cdrom' ]; then
1225 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1226 else
1227 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1228 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1229 install_package linux-squashfs $version || return 1
1230 done
1231 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1232 $TMP_DIR/initfs/lib/modules
1233 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1234 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1235 fi
1236 if [ "$1" == 'http' ]; then
1237 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1238 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1239 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1240 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1241 cp -a /dev/fuse $TMP_DIR/initfs/dev
1242 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1243 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1244 else
1245 need_lib=true
1246 fi
1247 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1248 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1249 else
1250 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1251 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1252 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1253 cp -a /lib/librt* $TMP_DIR/initfs/lib
1254 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1255 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1256 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1257 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1258 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1259 need_lib=true
1260 fi
1261 cd $TMP_DIR/fs
1262 echo 'Getting slitaz-release & ethernet modules...'
1263 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1264 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1265 [ -s rootfs* ] || continue
1266 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1267 rm -f rootfs*
1268 done 2>&1 > /dev/null
1269 cd - > /dev/null
1270 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1271 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1272 -type f -name '*.ko*' | while read mod; do
1273 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1274 uncompress $mod > $f
1275 grep -q alias=pci: $f || rm -f $f
1276 done
1277 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1278 f=$(basename $i)..z
1279 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1280 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1281 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1282 for j in $deps; do
1283 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1284 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1285 done
1286 done
1287 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"
1288 _n 'List of URLs to insert: '
1289 read -t 30 urliso2
1290 urliso="$urliso2 $urliso"
1291 fi
1292 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1293 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1294 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1295 else
1296 cp /bin/busybox $TMP_DIR/initfs/bin
1297 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1298 cp /sbin/insmod $TMP_DIR/initfs/bin
1299 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1300 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1301 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1302 fi
1303 need_lib=true
1304 fi
1305 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1306 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1307 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1308 done
1309 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1310 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1311 $TMP_DIR/initfs/lib/modules 2>/dev/null
1312 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1313 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1314 cp -a $i $TMP_DIR/initfs/dev
1315 done
1316 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1317 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1318 cp -a $i $TMP_DIR/initfs/dev
1319 done 2>/dev/null
1320 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1321 cp -a $i $TMP_DIR/initfs/lib
1322 done
1323 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1324 #!/bin/sh
1326 getarg() {
1327 grep -q " \$1=" /proc/cmdline || return 1
1328 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1329 return 0
1332 copy_rootfs() {
1333 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1334 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1335 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1336 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1337 path=/mnt/
1338 return 0
1339 else
1340 rm -f /mnt/rootfs*
1341 return 1
1342 fi
1345 echo "Switching / to tmpfs..."
1346 mount -t proc proc /proc
1347 size="\$(grep rootfssize= < /proc/cmdline | \\
1348 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1349 [ -n "\$size" ] || size="-o size=90%"
1351 mount -t sysfs sysfs /sys
1352 for i in /lib/modules/*.ko ; do
1353 echo -en "Probe \$i \\r"
1354 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1355 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1356 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1357 insmod /lib/modules/\$k.ko 2> /dev/null
1358 done
1359 echo "Loading \$i"
1360 insmod \$i 2> /dev/null
1361 break
1362 done
1363 done
1364 umount /sys
1365 while read var default; do
1366 eval \$var=\$default
1367 getarg \$var \$var
1368 done <<EOT
1369 eth eth0
1370 dns 208.67.222.222,208.67.220.220
1371 netmask 255.255.255.0
1372 gw
1373 ip
1374 EOT
1375 grep -q \$eth /proc/net/dev || sh
1376 if [ -n "\$ip" ]; then
1377 ifconfig \$eth \$ip netmask \$netmask up
1378 route add default gateway \$gw
1379 for i in \$(echo \$dns | sed 's/,/ /g'); do
1380 echo "nameserver \$i" >> /etc/resolv.conf
1381 done
1382 else
1383 udhcpc -f -q -s /lib/udhcpc -i \$eth
1384 fi
1385 for i in $urliso ; do
1386 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1387 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"
1388 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1389 done
1390 getarg urliso URLISO
1391 DIR=fs
1392 if getarg loram DIR; then
1393 DEVICE=\${DIR%,*}
1394 DIR=/\${DIR#*,}
1395 fi
1396 mount -t tmpfs \$size tmpfs /mnt
1397 path2=/mnt/.httpfs/
1398 path=/mnt/.cdrom/
1399 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1400 while [ ! -d \$path/boot ]; do
1401 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1402 httpfs \$i \$path2 && echo \$i && break
1403 done
1404 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1405 done
1407 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1408 umount /proc
1409 branch=:/mnt/.cdrom/\$DIR
1410 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1411 branch=
1412 lp=1
1413 insmod /lib/modules/squashfs.ko 2> /dev/null
1414 for i in \${path}boot/rootfs?.* ; do
1415 fs=\${i#*root}
1416 branch=\$branch:/mnt/.\$fs
1417 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1418 losetup -o 124 /dev/loop\$lp \$i
1419 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1420 lp=\$((\$lp+1))
1421 done
1422 fi
1423 mkdir -p /mnt/.rw/mnt/.httpfs
1424 while read type opt; do
1425 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1426 done <<EOT
1427 aufs br=/mnt/.rw\$branch
1428 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1429 EOT
1430 rm -rf /lib/modules
1431 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1432 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1433 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1434 EOTEOT
1435 chmod +x $TMP_DIR/initfs/init
1436 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1437 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1438 rm -f $i
1439 done 2>/dev/null
1440 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1441 lzma e $TMP_DIR/initfs.gz -si
1442 lzma_set_size $TMP_DIR/initfs.gz
1443 rm -rf $TMP_DIR/initfs
1444 align_to_32bits $TMP_DIR/initfs.gz
1445 return 0
1449 # Move each initramfs to squashfs
1451 build_loram_rootfs() {
1452 rootfs_sizes=""
1453 for i in $TMP_DIR/iso/boot/rootfs*; do
1454 mkdir -p $TMP_DIR/fs
1455 cd $TMP_DIR/fs
1456 uncompress $i | cpio -idm
1457 deduplicate
1458 cd - > /dev/null
1459 rootfs=$TMP_DIR/$(basename $i)
1460 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1461 cd $TMP_DIR
1462 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1463 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1464 rm -f $rootfs
1465 mv $rootfs.cpio $rootfs
1466 cd - > /dev/null
1467 rm -rf $TMP_DIR/fs
1468 done
1472 # Move meta boot configuration files to basic configuration files
1473 # because meta loram flavor is useless when rootfs is not loaded in RAM
1475 unmeta_boot() {
1476 local root=${1:-$TMP_DIR/loramiso}
1477 if [ -f $root/boot/isolinux/noram.cfg ]; then
1478 # We keep enough information to do unloram...
1479 [ -s $root/boot/isolinux/common.cfg ] &&
1480 sed -i 's/label slitaz/label orgslitaz/' \
1481 $root/boot/isolinux/common.cfg
1482 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1483 shift
1484 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1485 $root/boot/isolinux/isolinux.cfg
1486 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1487 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1488 $root/boot/isolinux/*.cfg
1489 fi
1493 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1494 # These squashfs may be loaded in RAM at boot time.
1495 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1496 # Meta flavors are converted to normal flavors.
1498 build_loram_cdrom() {
1499 build_initfs cdrom || return 1
1500 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1501 mkdir $TMP_DIR/loramiso/fs
1502 cd $TMP_DIR/loramiso/fs
1503 for i in $( ls ../boot/root* | sort -r ) ; do
1504 uncompress $i | cpio -idmu
1505 rm -f $i
1506 done
1507 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1508 cd - >/dev/null
1509 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1510 unmeta_boot
1511 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1512 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1513 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1514 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1515 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1516 create_iso $OUTPUT $TMP_DIR/loramiso
1520 # Create http bootstrap to load and remove loram_cdrom
1521 # Meta flavors are converted to normal flavors.
1523 build_loram_http() {
1524 build_initfs http || return 1
1525 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1526 rm -f $TMP_DIR/loramiso/boot/rootfs*
1527 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1528 unmeta_boot
1529 create_iso $OUTPUT $TMP_DIR/loramiso
1533 # Update meta flavor selection sizes.
1534 # Reduce sizes with rootfs gains.
1536 update_metaiso_sizes() {
1537 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1538 do
1539 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1540 local sizes="$rootfs_sizes"
1541 local new
1542 set -- $append
1543 shift
1544 [ "$1" == "ifmem" ] && shift
1545 new=""
1546 while [ -n "$2" ]; do
1547 local s
1548 case "$1" in
1549 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1550 *M) s=$(( ${1%M} * 1024 ));;
1551 *) s=${1%K};;
1552 esac
1553 sizes=${sizes#* }
1554 for i in $sizes ; do
1555 s=$(( $s - $i ))
1556 done
1557 new="$new $s $2"
1558 shift 2
1559 done
1560 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1561 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1562 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1563 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1564 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1565 done
1569 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1570 # Meta flavor selection sizes are updated.
1572 build_loram_ram() {
1573 build_initfs ram || return 1
1574 build_loram_rootfs "$1"
1575 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1576 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1577 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1578 update_metaiso_sizes
1579 create_iso $OUTPUT $TMP_DIR/loramiso
1583 # Remove files installed by packages
1585 find_flavor_rootfs() {
1586 for i in $1/etc/tazlito/*.extract; do
1587 [ -e $i ] || continue
1588 chroot $1 /bin/sh ${i#$1}
1589 done
1591 # Clean hardlinks and files patched by genisofs in /boot
1592 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1593 rm -f $1/boot/$i*
1594 done
1596 # Clean files generated in post_install
1597 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1598 $1/dev/core $1/dev/fd $1/dev/std*
1600 # Verify md5
1601 cat $1$INSTALLED/*/md5sum | \
1602 while read md5 file; do
1603 [ -e "$1$file" ] || continue
1604 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1605 rm -f "$1$file"
1606 done
1608 # Check configuration files
1609 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1610 [ -e $i ] || continue
1611 mkdir /tmp/volatile$$
1612 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1613 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1614 while read file ; do
1615 [ -e "$1/$file" ] || continue
1616 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1617 done
1618 rm -rf /tmp/volatile$$
1619 done
1621 # Remove other files blindly
1622 for i in $1$INSTALLED/*/files.list; do
1623 for file in $(cat "$i"); do
1624 [ "$1$file" -nt "$i" ] && continue
1625 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1626 [ -d "$1$file" ] || rm -f "$1$file"
1627 done
1628 done
1630 # Remove tazpkg files and tmp files
1631 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1632 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1633 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1634 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1635 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1637 # Cleanup directory tree
1638 cd $1
1639 find * -type d | sort -r | while read dir; do
1640 rmdir "$dir" 2>/dev/null
1641 done
1642 cd - > /dev/null
1646 # Get byte(s) from a binary file
1648 get() {
1649 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1653 # Get cpio flavor info from the ISO image
1655 flavordata() {
1656 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1657 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1661 # Restore undigest mirrors
1663 restore_mirrors() {
1664 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1665 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1667 action 'Restoring mirrors...'
1668 if [ -d "$undigest.bak" ]; then
1669 [ -d "$undigest" ] && rm -r "$undigest"
1670 mv "$undigest.bak" "$undigest"
1671 fi
1672 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1673 :; status
1677 # Setup undigest mirrors
1679 setup_mirrors() {
1680 # Setup mirrors in plain system or in chroot (with variable root=)
1681 local mirrorlist="$1" fresh repacked
1682 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1684 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1685 restore_mirrors
1687 _ 'Setting up mirrors for %s...' "$root/"
1688 # Backing up current undigest mirrors and priority
1689 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1690 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1691 rm -rf '/var/www/tazlito/'
1692 mkdir -p '/var/www/tazlito/'
1694 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1695 fresh='/home/slitaz/packages'
1696 if [ -d "$fresh" ]; then
1697 # Setup first undigest mirror
1698 mkdir -p "$undigest/fresh"
1699 echo "$fresh" > "$undigest/fresh/mirror"
1700 echo 'fresh' >> "$priority"
1701 # Rebuild mirror DB if needed
1702 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1703 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1704 tazpkg mkdb "$fresh" --forced --root=''
1705 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1706 fi
1708 # Repacked packages: high priority
1709 repacked="$PACKAGES_REPOSITORY"
1710 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1711 # According to Tazlito setup file (tazlito.conf):
1712 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1713 # or
1714 # WORK_DIR="/home/slitaz"
1715 # and
1716 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1717 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1719 # Setup second undigest mirror
1720 mkdir -p "$undigest/repacked"
1721 echo "$repacked" > "$undigest/repacked/mirror"
1722 echo 'repacked' >> "$priority"
1723 # Rebuild mirror DB if needed
1724 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1725 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1726 tazpkg mkdb "$repacked" --forced --root=''
1727 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1728 fi
1730 # All repositories listed in mirrors list: normal priority
1731 [ -e "$mirrorlist" ] && \
1732 while read mirror; do
1733 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1734 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1735 mkdir -p "$undigest/$mirrorid"
1736 echo "$mirror" > "$undigest/$mirrorid/mirror"
1737 echo "$mirrorid" >> "$priority"
1738 done < "$mirrorlist"
1740 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1742 # Show list of mirrors
1743 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1744 function show(num, name, url) {
1745 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1748 num++;
1749 "cat " db "/undigest/" $0 "/mirror" | getline url;
1750 show(num, $0, url);
1752 END {
1753 num++;
1754 "cat " db "/mirror" | getline url;
1755 show(num, "main", url);
1756 }' "$priority"
1758 tazpkg recharge --quiet >/dev/null
1762 # Get list of 'packages.info' lists using priority
1764 pi_lists() {
1765 local pi
1766 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1767 local priority="$root$LOCALSTATE/priority"
1768 local undigest="$root$LOCALSTATE/undigest"
1771 [ -s "$priority" ] && cat "$priority"
1772 echo 'main'
1773 [ -d "$undigest" ] && ls "$undigest"
1774 } | awk -vun="$undigest/" '
1776 if (arr[$0] != 1) {
1777 arr[$0] = 1;
1778 print un $0 "/packages.info";
1780 }' | sed 's|/undigest/main||' | \
1781 while read pi; do
1782 [ -e "$pi" ] && echo "$pi"
1783 done
1787 # Strip versions from packages list
1789 strip_versions() {
1790 if [ -n "$stripped" ]; then
1791 action 'Consider list %s already stripped' "$(basename "$1")"
1792 status
1793 return 0
1794 fi
1795 action 'Strip versions from list %s...' "$(basename "$1")"
1796 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1797 [ -f "$in_list" ] || die "List '$in_list' not found."
1799 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1800 awk '
1802 if (FILENAME ~ "packages.info") {
1803 # Collect package names
1804 FS = "\t"; pkg[$1] = 1;
1805 } else {
1806 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1807 while (NF > 1 && ! pkg[$0])
1808 NF --;
1809 printf "%s\n", $0;
1811 }' $(pi_lists) "$in_list" > "$tmp_list"
1813 cat "$tmp_list" > "$in_list"
1814 rm "$tmp_list"
1815 status
1819 # Display list of unknown packages (informative)
1821 display_unknown() {
1822 [ -s "$1" ] || return
1823 echo "Unknown packages:" >&2
1824 cat "$1" >&2
1825 rm "$1"
1829 # Display warnings about critical packages absent (informative)
1831 display_warn() {
1832 [ -s "$1" ] || return
1833 echo "Absent critical packages:" >&2
1834 cat "$1" >&2
1835 rm "$1"
1836 echo "Probably ISO image will be unusable."
1840 # Install packages to rootfs
1842 install_list_to_rootfs() {
1843 local list="$1" rootfs="$2" pkg i ii
1844 local undigest="$rootfs/var/lib/tazpkg/undigest"
1846 # initial tazpkg setup in empty rootfs
1847 tazpkg --root=$rootfs >/dev/null 2>&1
1848 # pass current 'mirror' to the rootfs
1849 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1850 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1851 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1852 # link rootfs packages cache to the regular packages cache
1853 rm -r "$rootfs/var/cache/tazpkg"
1854 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1856 setup_mirrors mirrors
1858 # Just in case if flavor doesn't contain "tazlito" package
1859 mkdir -p "$rootfs/etc/tazlito"
1861 newline
1863 # Choose detailed log with --detailed
1864 if [ -n "$detailed" ]; then
1865 while read pkg; do
1866 separator '-'
1867 echo $pkg
1868 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1869 done < $list
1870 separator '='
1871 else
1872 while read pkg; do
1873 action 'Installing package: %s' "$pkg"
1874 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1875 status
1876 done < $list
1877 fi
1878 newline
1880 restore_mirrors
1881 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1882 for i in fresh repacked; do
1883 ii="$undigest/$i"
1884 [ -d "$ii" ] && rm -rf "$ii"
1885 ii="$rootfs/var/lib/tazpkg/priority"
1886 if [ -f "$ii" ]; then
1887 sed -i "/$i/d" "$ii"
1888 [ -s "$ii" ] || rm "$ii"
1889 fi
1890 done
1891 [ -d "$undigest" ] && \
1892 for i in $(find "$undigest" -type f); do
1893 # Remove all undigest PKGDB files but 'mirror'
1894 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1895 done
1896 [ -d "$undigest" ] && \
1897 rmdir --ignore-fail-on-non-empty "$undigest"
1899 # Un-link packages cache
1900 rm "$rootfs/var/cache/tazpkg"
1902 # Clean /var/lib/tazpkg
1903 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1909 ####################
1910 # Tazlito commands #
1911 ####################
1913 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1914 case "$0" in
1915 *reduplicate)
1916 find ${@:-.} ! -type d -links +1 \
1917 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1918 exit 0 ;;
1919 *deduplicate)
1920 deduplicate "$@"
1921 exit 0 ;;
1922 esac
1925 case "$COMMAND" in
1926 stats)
1927 # Tazlito general statistics from the config file.
1929 title 'Tazlito statistics'
1930 optlist "\
1931 Config file : $CONFIG_FILE
1932 ISO name : $ISO_NAME.iso
1933 Volume name : $VOLUM_NAME
1934 Prepared : $PREPARED
1935 Packages repository : $PACKAGES_REPOSITORY
1936 Distro directory : $DISTRO
1937 Additional files : $ADDFILES
1938 " | sed '/: $/d'
1939 footer
1940 ;;
1943 list-addfiles)
1944 # Simple list of additional files in the rootfs
1945 newline
1946 if [ -d "$ADDFILES/rootfs" ]; then
1947 cd $ADDFILES
1948 find rootfs -type f
1949 else
1950 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1951 fi
1952 newline
1953 ;;
1956 gen-config)
1957 # Generate a new config file in the current dir or the specified
1958 # directory by $2.
1960 if [ -n "$2" ]; then
1961 mkdir -p "$2" && cd "$2"
1962 fi
1964 newline
1965 action 'Generating empty tazlito.conf...'
1966 empty_config_file
1967 status
1969 separator
1970 if [ -f 'tazlito.conf' ] ; then
1971 _ 'Configuration file is ready to edit.'
1972 _ 'File location: %s' "$(pwd)/tazlito.conf"
1973 newline
1974 fi
1975 ;;
1978 configure)
1979 # Configure a tazlito.conf config file. Start by getting
1980 # a empty config file and sed it.
1982 if [ -f 'tazlito.conf' ]; then
1983 rm tazlito.conf
1984 else
1985 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1986 'or in the same directory of the file you want to configure.'
1987 cd /etc
1988 fi
1990 empty_config_file
1992 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1994 # ISO name.
1995 echo -n "ISO name : " ; read answer
1996 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1997 # Volume name.
1998 echo -n "Volume name : " ; read answer
1999 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2000 # Packages repository.
2001 echo -n "Packages repository : " ; read answer
2002 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2003 # Distro path.
2004 echo -n "Distro path : " ; read answer
2005 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2006 footer "Config file is ready to use."
2007 echo 'You can now extract an ISO or generate a distro.'
2008 newline
2009 ;;
2012 gen-iso)
2013 # Simply generate a new iso.
2015 check_root
2016 verify_rootcd
2017 gen_livecd_isolinux
2018 distro_stats
2019 ;;
2022 gen-initiso)
2023 # Simply generate a new initramfs with a new iso.
2025 check_root
2026 verify_rootcd
2027 gen_initramfs "$ROOTFS"
2028 gen_livecd_isolinux
2029 distro_stats
2030 ;;
2033 extract-distro)
2034 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2036 check_root
2037 ISO_IMAGE="$2"
2038 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2039 'Example:\n tazlito image.iso /path/target'
2041 # Set the distro path by checking for $3 on cmdline.
2042 TARGET="${3:-$DISTRO}"
2044 # Exit if existing distro is found.
2045 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2046 'Please clean the distro tree or change directory path.'
2048 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2050 # Start to mount the ISO.
2051 action 'Mounting ISO image...'
2052 mkdir -p "$TMP_DIR"
2053 # Get ISO file size.
2054 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2055 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2056 sleep 2
2057 # Prepare target dir, copy the kernel and the rootfs.
2058 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2059 status
2061 action 'Copying the Linux kernel...'
2062 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2063 make_bzImage_hardlink "$TARGET/rootcd/boot"
2064 else
2065 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2066 fi
2067 status
2069 for i in $(ls $TMP_DIR); do
2070 [ "$i" == 'boot' ] && continue
2071 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2072 done
2074 for loader in isolinux syslinux extlinux grub; do
2075 [ -d "$TMP_DIR/boot/$loader" ] || continue
2076 action 'Copying %s files...' "$loader"
2077 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2078 status
2079 done
2081 action 'Copying the rootfs...'
2082 cp $TMP_DIR/boot/rootfs*.?z "$TARGET/rootcd/boot"
2083 status
2085 # Extract initramfs.
2086 cd "$TARGET/rootfs"
2087 action 'Extracting the rootfs...'
2088 for i in $(ls -r $TARGET/rootcd/boot/rootfs*); do
2089 extract_rootfs "$i" "$TARGET/rootfs"
2090 done
2091 # unpack /usr
2092 for i in etc/tazlito/*.extract; do
2093 [ -f "$i" ] && . $i ../rootcd
2094 done
2095 # Umount and remove temp directory and cd to $TARGET to get stats.
2096 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2097 cd ..
2098 status
2100 newline
2101 separator
2102 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2103 echo "Distro tree : $(pwd)"
2104 echo "Rootfs size : $(du -sh rootfs)"
2105 echo "Rootcd size : $(du -sh rootcd)"
2106 footer
2107 ;;
2110 list-flavors)
2111 # Show available flavors.
2112 list='/etc/tazlito/flavors.list'
2113 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2114 title 'List of flavors'
2115 cat $list
2116 footer
2117 ;;
2120 show-flavor)
2121 # Show flavor descriptions.
2122 set -e
2123 flavor=${2%.flavor}
2124 flv_dir="$(extract_flavor "$flavor")"
2125 desc="$flv_dir/$flavor.desc"
2126 if [ -n "$brief" ]; then
2127 if [ -z "$noheader" ]; then
2128 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2129 separator
2130 fi
2131 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2132 "$(field ISO "$desc")" \
2133 "$(field Rootfs "$desc")" \
2134 "$(field Description "$desc")"
2135 else
2136 separator
2137 cat "$desc"
2138 fi
2139 cleanup
2140 ;;
2143 gen-liveflavor)
2144 # Generate a new flavor from the live system.
2145 FLAVOR=${2%.flavor}
2146 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2148 case "$FLAVOR" in
2149 -?|-h*|--help)
2150 cat <<EOT
2151 SliTaz Live Tool - Version: $VERSION
2153 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2155 $(boldify '<flavor-patch-file> format:')
2156 $(optlist "\
2157 code data
2158 + package to add
2159 - package to remove
2160 ! non-free package to add
2161 ? display message
2162 @ flavor description
2163 ")
2165 $(boldify 'Example:')
2166 $(optlist "\
2167 @ Developer tools for SliTaz maintainers
2168 + slitaz-toolchain
2169 + mercurial
2170 ")
2171 EOT
2172 exit 1
2173 ;;
2174 esac
2175 mv /etc/tazlito/distro-packages.list \
2176 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2177 rm -f distro-packages.list non-free.list 2>/dev/null
2178 tazpkg recharge
2180 DESC=""
2181 [ -n "$3" ] && \
2182 while read action pkg; do
2183 case "$action" in
2184 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2185 -) yes | tazpkg remove $pkg ;;
2186 !) echo $pkg >> non-free.list ;;
2187 @) DESC="$pkg" ;;
2188 \?) echo -en "$pkg"; read action ;;
2189 esac
2190 done < $3
2192 yes '' | tazlito gen-distro
2193 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2194 mv /etc/tazlito/distro-packages.list.$$ \
2195 /etc/tazlito/distro-packages.list 2>/dev/null
2196 ;;
2199 gen-flavor)
2200 # Generate a new flavor from the last ISO image generated
2201 FLAVOR=${2%.flavor}
2202 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2204 title 'Flavor generation'
2205 check_rootfs
2206 FILES="$FLAVOR.pkglist"
2208 action 'Creating file %s...' "$FLAVOR.flavor"
2209 for i in rootcd rootfs; do
2210 if [ -d "$ADDFILES/$i" ] ; then
2211 FILES="$FILES\n$FLAVOR.$i"
2212 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2213 fi
2214 done
2215 status
2217 answer=$(grep -s ^Description $FLAVOR.desc)
2218 answer=${answer#Description : }
2219 if [ -z "$answer" ]; then
2220 echo -n "Description: "
2221 read answer
2222 fi
2224 action 'Compressing flavor %s...' "$FLAVOR"
2225 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2226 echo "Description : $answer" >> $FLAVOR.desc
2227 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2228 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2229 for i in $(ls $ROOTFS$INSTALLED); do
2230 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2231 EXTRAVERSION=""
2232 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2233 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2234 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2235 echo "$i" >> $FLAVOR.nonfree
2236 else
2237 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2238 fi
2239 done
2240 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2241 for i in $LOCALSTATE/undigest/*/mirror ; do
2242 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2243 done
2244 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2245 touch -t 197001010100.00 $FLAVOR.*
2246 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2247 rm $(echo -e $FILES)
2248 status
2250 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2251 ;;
2254 upgrade-flavor)
2255 # Strip versions from pkglist and update estimated numbers in flavor.desc
2256 flavor="${2%.flavor}"
2257 set -e
2258 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2259 set +e
2261 flv_dir="$(extract_flavor "$flavor")"
2263 strip_versions "$flv_dir/$flavor.pkglist"
2265 action 'Updating %s...' "$flavor.desc"
2267 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2268 set -- $(module calc_sizes "$flv_dir" "$flavor")
2269 restore_mirrors >/dev/null
2271 sed -i -e '/Image is ready/d' \
2272 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2273 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2274 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2275 -e "s|\(Packages *:\).*$|\1 $4|" \
2276 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2277 "$flv_dir/$flavor.desc"
2279 pack_flavor "$flv_dir" "$flavor"
2280 status
2281 display_unknown "$flv_dir/err"
2282 display_warn "$flv_dir/warn"
2283 cleanup
2284 ;;
2287 extract-flavor)
2288 # Extract a flavor into $FLAVORS_REPOSITORY
2289 flavor="${2%.flavor}"
2290 set -e
2291 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2292 set +e
2294 action 'Extracting %s...' "$flavor.flavor"
2295 flv_dir="$(extract_flavor "$flavor" full)"
2296 storage="$FLAVORS_REPOSITORY/$flavor"
2298 rm -rf "$storage" 2>/dev/null
2299 mkdir -p "$storage"
2300 cp -a "$flv_dir"/* "$storage"
2301 rm "$storage/description"
2302 status
2304 strip_versions "$storage/packages.list"
2306 cleanup
2307 ;;
2310 pack-flavor)
2311 # Create a flavor from $FLAVORS_REPOSITORY.
2312 flavor=${2%.flavor}
2313 storage="$FLAVORS_REPOSITORY/$flavor"
2315 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2317 action 'Creating flavor %s...' "$flavor"
2318 tmp_dir="$(mktemp -d)"
2320 while read from to; do
2321 [ -s "$storage/$from" ] || continue
2322 cp -a "$storage/$from" "$tmp_dir/$to"
2323 done <<EOT
2324 mirrors $flavor.mirrors
2325 distro.sh $flavor-distro.sh
2326 receipt $flavor.receipt
2327 non-free.list $flavor.nonfree
2328 EOT
2330 # Build the package list.
2331 # It can include a list from another flavor with the keyword @include
2332 if [ -s "$storage/packages.list" ]; then
2333 include=$(grep '^@include' "$storage/packages.list")
2334 if [ -n "$include" ]; then
2335 include=${include#@include }
2336 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2337 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2338 else
2339 echo -e "\nERROR: Can't find include package list from $include\n"
2340 fi
2341 fi
2342 # Generate the final/initial package list
2343 [ -s "$storage/packages.list" ] && \
2344 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2345 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2346 fi
2348 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2349 # Process multi-rootfs flavor
2350 . "$storage/receipt"
2351 set -- $ROOTFS_SELECTION
2352 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2353 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2354 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2356 for i in rootcd rootfs; do
2357 mkdir "$tmp_dir/$i"
2358 # Copy extra files from the first flavor
2359 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2360 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2361 # Overload extra files by meta flavor
2362 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2363 [ -n "$(ls $tmp_dir/$i)" ] &&
2364 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2365 dogzip "$tmp_dir/$flavor.$i"
2366 rm -rf "$tmp_dir/$i"
2367 done
2368 else
2369 # Process plain flavor
2370 for i in rootcd rootfs; do
2371 [ -d "$storage/$i" ] || continue
2372 (cd "$storage/$i";
2373 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2374 done
2375 fi
2377 unset VERSION MAINTAINER ROOTFS_SELECTION
2378 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2379 ROOTFS_SIZE="$1 (estimated)"
2380 INITRAMFS_SIZE="$2 (estimated)"
2381 ISO_SIZE="$3 (estimated)"
2382 PKGNUM="$4"
2383 . "$storage/receipt"
2385 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2386 Flavor : $FLAVOR
2387 Description : $SHORT_DESC
2388 Version : $VERSION
2389 Maintainer : $MAINTAINER
2390 LiveCD RAM size : $FRUGAL_RAM
2391 Rootfs list : $ROOTFS_SELECTION
2392 Build date : $(date '+%Y%m%d at %T')
2393 Packages : $PKGNUM
2394 Rootfs size : $ROOTFS_SIZE
2395 Initramfs size : $INITRAMFS_SIZE
2396 ISO image size : $ISO_SIZE
2397 ================================================================================
2399 EOT
2401 rm -f $tmp_dir/packages.list
2402 pack_flavor "$tmp_dir" "$flavor"
2403 status
2404 display_unknown "$tmp_dir/err"
2405 display_warn "$flv_dir/warn"
2406 cleanup
2407 ;;
2410 get-flavor)
2411 # Get a flavor's files and prepare for gen-distro.
2412 flavor=${2%.flavor}
2413 title 'Preparing %s distro flavor' "$flavor"
2414 set -e
2415 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2416 set +e
2418 action 'Cleaning %s...' "$DISTRO"
2419 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2420 # Clean old files
2421 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2422 [ -f "$i" ] && rm "$i"
2423 done
2424 mkdir -p "$DISTRO"
2425 status
2427 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2429 action 'Extracting flavor %s...' "$flavor.flavor"
2430 flv_dir="$(extract_flavor "$flavor" info)"
2431 cp -a "$flv_dir"/* .
2432 mv packages.list distro-packages.list
2433 mv -f info /etc/tazlito
2434 status
2436 for i in rootcd rootfs; do
2437 if [ -d "$i" ]; then
2438 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2439 fi
2440 done
2442 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2443 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2445 action 'Updating %s...' 'tazlito.conf'
2446 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2447 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2448 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2449 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2450 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2451 status
2453 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2454 cleanup
2455 ;;
2458 iso2flavor)
2459 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2460 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2462 FLAVOR=${3%.flavor}
2463 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2464 mount -o loop,ro $2 $TMP_DIR/iso
2465 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2466 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2467 ! -s $TMP_DIR/flavor/*.desc ]; then
2468 _ 'META flavors are not supported.'
2469 umount -d $TMP_DIR/iso
2470 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2471 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2472 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2473 umount -d $TMP_DIR/iso
2474 else
2475 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2476 uncompress $i | \
2477 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2478 done
2479 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2480 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2481 '/etc/slitaz-release' '/boot/rootfs.gz'
2482 umount -d $TMP_DIR/iso
2483 else
2484 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2485 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2486 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2487 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2488 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2489 umount -d $TMP_DIR/iso
2490 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2491 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2492 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2493 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2494 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2495 < $TMP_DIR/rootfs$INSTALLED.md5
2496 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2497 if [ -s $TMP_DIR/flavor/*desc ]; then
2498 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2499 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2500 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2501 for i in rootfs rootcd ; do
2502 [ -s $TMP_DIR/flavor/*.list$i ] &&
2503 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2504 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2505 done
2506 else
2507 find_flavor_rootfs $TMP_DIR/rootfs
2508 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2509 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2510 for i in rootfs rootcd ; do
2511 [ "$(ls $TMP_DIR/$i)" ] &&
2512 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2513 done
2514 unset VERSION MAINTAINER
2515 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2516 if [ -n "$DESCRIPTION" ]; then
2517 _n 'Flavor version : '; read -t 30 VERSION
2518 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2519 fi
2521 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2522 Flavor : $FLAVOR
2523 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2524 Version : ${VERSION:-1.0}
2525 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2526 LiveCD RAM size : $RAM_SIZE
2527 Build date : $BUILD_DATE
2528 Packages : $PKGCNT
2529 Rootfs size : $ROOTFS_SIZE
2530 Initramfs size : $INITRAMFS_SIZE
2531 ISO image size : $ISO_SIZE
2532 ================================================================================
2534 EOT
2535 longline "Tazlito can't detect each file installed during \
2536 a package post_install. You should extract this flavor (tazlito extract-flavor \
2537 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2538 tree and remove files generated by post_installs.
2539 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2540 repack the flavor (tazlito pack-flavor $FLAVOR)"
2541 fi
2542 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2543 fi
2544 fi
2545 rm -rf $TMP_DIR
2546 ;;
2549 gen-distro)
2550 # Generate a live distro tree with a set of packages.
2552 check_root
2553 start_time=$(date +%s)
2555 # Tazlito options: --iso or --cdrom
2556 CDROM=''
2557 [ -n "$iso" ] && CDROM="-o loop $iso"
2558 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2560 # Check if a package list was specified on cmdline.
2561 if [ -f "$2" ]; then
2562 LIST_NAME="$2"
2563 else
2564 LIST_NAME='distro-packages.list'
2565 fi
2567 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2568 'Please clean the distro tree or change directory path.'
2569 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2570 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2572 # If list not given: build list with all installed packages
2573 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2574 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2575 fi
2577 # Exit if no list name.
2578 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2580 # Start generation.
2581 title 'Tazlito generating a distro'
2583 # Misc checks
2584 mkdir -p "$PACKAGES_REPOSITORY"
2585 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2586 newline
2588 # Mount CD-ROM to be able to repack boot-loader packages
2589 if [ ! -e /boot -a -n "$CDROM" ]; then
2590 mkdir $TMP_MNT
2591 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2592 ln -s "$TMP_MNT/boot" /
2593 if [ ! -d "$ADDFILES/rootcd" ] ; then
2594 mkdir -p "$ADDFILES/rootcd"
2595 for i in $(ls $TMP_MNT); do
2596 [ "$i" == 'boot' ] && continue
2597 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2598 done
2599 fi
2600 else
2601 rmdir "$TMP_MNT"
2602 fi
2603 fi
2605 # Rootfs stuff.
2606 echo 'Preparing the rootfs directory...'
2607 mkdir -p "$ROOTFS"
2608 export root="$ROOTFS"
2609 # pass current 'mirror' to the root
2610 mkdir -p $root/var/lib/tazpkg $root/etc
2611 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2612 cp -f /etc/slitaz-release $root/etc/slitaz-release
2613 strip_versions "$LIST_NAME"
2615 if [ "$REPACK" == 'y' ]; then
2616 # Determine full packages list with all dependencies
2617 tmp_dir="$(mktemp -d)"
2618 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2619 touch "$tmp_dir/full.pkglist"
2620 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2622 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2623 while read pkgname pkgver; do
2624 # Is package in full list?
2625 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2626 # Is package already repacked?
2627 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2628 _ 'Repacking %s...' "$pkgname-$pkgver"
2629 tazpkg repack "$pkgname" --quiet
2630 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2631 status
2632 done
2634 rm -r "$tmp_dir"
2635 fi
2637 if [ -f non-free.list ]; then
2638 # FIXME: working in the ROOTFS chroot?
2639 newline
2640 echo 'Preparing non-free packages...'
2641 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2642 for pkg in $(cat 'non-free.list'); do
2643 if [ ! -d "$INSTALLED/$pkg" ]; then
2644 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2645 tazpkg get-install get-$pkg
2646 fi
2647 get-$pkg "$ROOTFS"
2648 fi
2649 tazpkg repack $pkg
2650 pkg=$(ls $pkg*.tazpkg)
2651 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2652 mv $pkg $PACKAGES_REPOSITORY
2653 done
2654 fi
2655 cp $LIST_NAME $DISTRO/distro-packages.list
2656 newline
2658 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2660 cd $DISTRO
2661 cp distro-packages.list $ROOTFS/etc/tazlito
2662 # Copy all files from $ADDFILES/rootfs to the rootfs.
2663 if [ -d "$ADDFILES/rootfs" ] ; then
2664 action 'Copying addfiles content to the rootfs...'
2665 cp -a $ADDFILES/rootfs/* $ROOTFS
2666 status
2667 fi
2669 action 'Root filesystem is generated...'; status
2671 # Root CD part.
2672 action 'Preparing the rootcd directory...'
2673 mkdir -p $ROOTCD
2674 status
2676 # Move the boot dir with the Linux kernel from rootfs.
2677 # The efi & boot dirs go directly on the CD.
2678 if [ -d "$ROOTFS/efi" ] ; then
2679 action 'Moving the efi directory...'
2680 mv $ROOTFS/efi $ROOTCD
2681 status
2682 fi
2683 if [ -d "$ROOTFS/boot" ] ; then
2684 action 'Moving the boot directory...'
2685 mv $ROOTFS/boot $ROOTCD
2686 status
2687 fi
2688 cd $DISTRO
2689 # Copy all files from $ADDFILES/rootcd to the rootcd.
2690 if [ -d "$ADDFILES/rootcd" ] ; then
2691 action 'Copying addfiles content to the rootcd...'
2692 cp -a $ADDFILES/rootcd/* $ROOTCD
2693 status
2694 fi
2695 # Execute the distro script used to perform tasks in the rootfs
2696 # before compression. Give rootfs path in arg
2697 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2698 if [ -x "$DISTRO_SCRIPT" ]; then
2699 echo 'Executing distro script...'
2700 sh $DISTRO_SCRIPT $DISTRO
2701 fi
2703 # Execute the custom_rules() found in receipt.
2704 if [ -s "$TOP_DIR/receipt" ]; then
2705 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2706 echo -e "Executing: custom_rules()\n"
2707 . "$TOP_DIR/receipt"
2708 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2709 fi
2710 fi
2712 # Multi-rootfs
2713 if [ -s /etc/tazlito/rootfs.list ]; then
2715 FLAVOR_LIST="$(awk '{
2716 for (i = 2; i <= NF; i+=2)
2717 printf "%s ", $i;
2718 }' /etc/tazlito/rootfs.list)"
2720 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2721 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2722 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2724 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2725 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2726 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2727 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2729 n=0
2730 last=$ROOTFS
2731 while read flavor; do
2732 n=$(($n+1))
2733 mkdir ${ROOTFS}0$n
2734 export root="${ROOTFS}0$n"
2735 # initial tazpkg setup in empty rootfs
2736 tazpkg --root=$root >/dev/null 2>&1
2738 newline
2739 boldify "Building $flavor rootfs..."
2741 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2742 cp "$TOP_DIR/$flavor.flavor" .
2744 if [ ! -s "$flavor.flavor" ]; then
2745 # We may have it in $FLAVORS_REPOSITORY
2746 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2747 tazlito pack-flavor $flavor
2748 else
2749 download $flavor.flavor
2750 fi
2751 fi
2753 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2754 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2755 cp $flavor.pkglist $DISTRO/list-packages0$n
2756 status
2758 strip_versions "$DISTRO/list-packages0$n"
2760 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2762 action 'Updating the boot directory...'
2763 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2764 rm -rf ${ROOTFS}0$n/boot
2766 cd $DISTRO
2767 if [ -s $flavor.rootfs ]; then
2768 _n 'Adding %s rootfs extra files...' "$flavor"
2769 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2770 fi
2772 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2773 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2774 status
2776 rm -f $flavor.flavor install-list
2777 mergefs ${ROOTFS}0$n $last
2778 last=${ROOTFS}0$n
2779 done <<EOT
2780 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2781 EOT
2782 #'
2783 i=$(($n+1))
2784 while [ $n -gt 0 ]; do
2785 mv ${ROOTFS}0$n ${ROOTFS}$i
2786 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2787 gen_initramfs ${ROOTFS}$i
2788 n=$(($n-1))
2789 i=$(($i-1))
2790 export LZMA_HISTORY_BITS=26
2791 done
2792 mv $ROOTFS ${ROOTFS}$i
2793 gen_initramfs ${ROOTFS}$i
2794 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2795 ROOTFS=${ROOTFS}1
2796 else
2797 # Initramfs and ISO image stuff.
2798 gen_initramfs $ROOTFS
2799 fi
2800 gen_livecd_isolinux
2801 distro_stats
2802 cleanup
2803 ;;
2806 clean-distro)
2807 # Remove old distro tree.
2809 check_root
2810 title 'Cleaning: %s' "$DISTRO"
2811 if [ -d "$DISTRO" ] ; then
2812 if [ -d "$ROOTFS" ] ; then
2813 action 'Removing the rootfs...'
2814 rm -f $DISTRO/$INITRAMFS
2815 rm -rf $ROOTFS
2816 status
2817 fi
2818 if [ -d "$ROOTCD" ] ; then
2819 action 'Removing the rootcd...'
2820 rm -rf $ROOTCD
2821 status
2822 fi
2823 action 'Removing eventual ISO image...'
2824 rm -f $DISTRO/$ISO_NAME.iso
2825 rm -f $DISTRO/$ISO_NAME.md5
2826 status
2827 fi
2828 footer
2829 ;;
2832 check-distro)
2833 # Check for a few LiveCD needed files not installed by packages.
2835 # TODO: Remove this function.
2836 # First two files are maintained by tazpkg while it runs on rootfs,
2837 # while last one file should be maintained by tazlito itself.
2838 check_rootfs
2839 title 'Checking distro: %s' "$ROOTFS"
2840 # SliTaz release info.
2841 rel='/etc/slitaz-release'
2842 if [ ! -f "$ROOTFS$rel" ]; then
2843 _ 'Missing release info: %s' "$rel"
2844 else
2845 action 'Release : %s' "$(cat $ROOTFS$rel)"
2846 status
2847 fi
2848 # Tazpkg mirror.
2849 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2850 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2851 todomsg
2852 else
2853 action 'Mirror configuration exists...'
2854 status
2855 fi
2856 # Isolinux msg
2857 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2858 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2859 todomsg
2860 else
2861 action 'Isolinux message seems good...'
2862 status
2863 fi
2864 footer
2865 ;;
2868 writeiso)
2869 # Writefs to ISO image including /home unlike gen-distro we don't use
2870 # packages to generate a rootfs, we build a compressed rootfs with all
2871 # the current filesystem similar to 'tazusb writefs'.
2873 DISTRO='/home/slitaz/distro'
2874 ROOTCD="$DISTRO/rootcd"
2875 COMPRESSION="${2:-none}"
2876 ISO_NAME="${3:-slitaz}"
2877 check_root
2878 # Start info
2879 title 'Write filesystem to ISO'
2880 longline "The command writeiso will write the current filesystem into a \
2881 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2882 newline
2883 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2885 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2886 # Save some space
2887 rm -rf /var/cache/tazpkg/*
2888 rm -f /var/lib/tazpkg/*.bak
2889 rm -rf $DISTRO
2891 # Optionally remove sound card selection and screen resolution.
2892 if [ -z $LaunchedByTazpanel ]; then
2893 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2894 case $anser in
2895 y)
2896 action 'Removing current sound card and screen configurations...'
2897 rm -f /var/lib/sound-card-driver
2898 rm -f /var/lib/alsa/asound.state
2899 rm -f /etc/X11/xorg.conf ;;
2900 *)
2901 action 'Keeping current sound card and screen configurations...' ;;
2902 esac
2903 status
2904 newline
2906 # Optionally remove i18n settings
2907 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2908 case $anser in
2909 y)
2910 action 'Removing current locale/keymap settings...'
2911 newline > /etc/locale.conf
2912 newline > /etc/keymap.conf ;;
2913 *)
2914 action 'Keeping current locale/keymap settings...' ;;
2915 esac
2916 status
2917 fi
2919 # Clean-up files by default
2920 newline > /etc/udev/rules.d/70-persistent-net.rules
2921 newline > /etc/udev/rules.d/70-persistant-cd.rules
2923 # Create list of files including default user files since it is defined in /etc/passwd
2924 # and some new users might have been added.
2925 cd /
2926 echo 'init' > /tmp/list
2927 for dir in bin etc sbin var dev lib root usr home opt; do
2928 [ -d $dir ] && find $dir
2929 done >> /tmp/list
2931 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2932 [ -d $dir ] && echo $dir
2933 done >> /tmp/list
2935 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2937 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2938 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2939 #fi
2940 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2941 touch /var/log/wtmp
2943 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2944 sed -i "/var\/log\/$removelog/d" /tmp/list
2945 done
2947 # Generate initramfs with specified compression and display rootfs
2948 # size in realtime.
2949 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2951 write_initramfs &
2952 sleep 2
2953 cd - > /dev/null
2954 echo -en "\nFilesystem size:"
2955 while [ ! -f /tmp/rootfs ]; do
2956 sleep 1
2957 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2958 done
2959 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2960 echo -e "\n"
2961 rm -f /tmp/rootfs
2963 # Move freshly generated rootfs to the cdrom.
2964 mkdir -p $ROOTCD/boot
2965 mv -f /$INITRAMFS $ROOTCD/boot
2966 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2968 # Now we need the kernel and isolinux files.
2969 copy_from_cd() {
2970 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2971 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2972 unmeta_boot $ROOTCD
2973 umount /media/cdrom
2976 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2977 copy_from_cd;
2978 elif mount | grep /media/cdrom; then
2979 copy_from_cd;
2980 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2981 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2982 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2983 else
2984 touch /tmp/.write-iso-error
2985 longline "When SliTaz is running in RAM the kernel and bootloader \
2986 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2987 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2988 echo -en "----\nENTER to continue..."; read i
2989 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2990 copy_from_cd
2991 fi
2993 # Generate the iso image.
2994 touch /tmp/.write-iso
2995 newline
2996 cd $DISTRO
2997 create_iso $ISO_NAME.iso $ROOTCD
2998 action 'Creating the ISO md5sum...'
2999 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3000 status
3002 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3003 rm -f /tmp/.write-iso
3005 if [ -z $LaunchedByTazpanel ]; then
3006 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3007 case $anser in
3008 y)
3009 umount /dev/cdrom 2>/dev/null
3010 eject
3011 echo -n "Please insert a blank CD-ROM and press ENTER..."
3012 read i && sleep 2
3013 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3014 echo -en "----\nENTER to continue..."; read i ;;
3015 *)
3016 exit 0 ;;
3017 esac
3018 fi
3019 ;;
3022 burn-iso)
3023 # Guess CD-ROM device, ask user and burn the ISO.
3025 check_root
3026 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3027 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3028 # We can specify an alternative ISO from the cmdline.
3029 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3030 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3032 title 'Tazlito burn ISO'
3033 echo "CD-ROM device : /dev/$DRIVE_NAME"
3034 echo "Drive speed : $DRIVE_SPEED"
3035 echo "ISO image : $iso"
3036 footer
3038 case $(yesorno 'Burn ISO image?' 'n') in
3039 y)
3040 title 'Starting Wodim to burn the ISO...'
3041 sleep 2
3042 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3043 footer 'ISO image is burned to CD-ROM.'
3044 ;;
3045 *)
3046 die 'Exiting. No ISO burned.'
3047 ;;
3048 esac
3049 ;;
3052 merge)
3053 # Merge multiple rootfs into one iso.
3055 if [ -z "$2" ]; then
3056 cat <<EOT
3057 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3059 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3060 i.e: rootfsN is a subset of rootfsN-1
3061 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3062 The boot loader will select the rootfs according to the RAM size detected.
3064 Example:
3065 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3067 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3068 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3070 EOT
3071 exit 2
3072 fi
3074 shift # skip merge
3075 append="$1 slitaz1"
3076 shift # skip size1
3077 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3079 ISO=$1.merged
3081 # Extract filesystems
3082 action 'Mounting %s' "$1"
3083 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3084 status || cleanup_merge
3086 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3087 make_bzImage_hardlink $TMP_DIR/iso/boot
3088 umount -d $TMP_DIR/mnt
3089 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3090 _ '%s is already a merged iso. Aborting.' "$1"
3091 cleanup_merge
3092 fi
3093 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3094 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3095 if [ ! -f /boot/isolinux/ifmem.c32 -a
3096 ! -f /boot/isolinux/c32box.c32 ]; then
3097 cat <<EOT
3098 No file /boot/isolinux/ifmem.c32
3099 Please install syslinux package !
3100 EOT
3101 rm -rf $TMP_DIR
3102 exit 1
3103 fi
3104 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3105 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3106 fi
3108 action 'Extracting %s' 'iso/rootfs.gz'
3109 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3110 [ -d $TMP_DIR/rootfs1/etc ]
3111 status || cleanup_merge
3113 n=1
3114 while [ -n "$2" ]; do
3115 shift # skip rootfs N-1
3116 p=$n
3117 n=$(($n + 1))
3118 append="$append $1 slitaz$n"
3119 shift # skip size N
3120 mkdir -p $TMP_DIR/rootfs$n
3122 action 'Extracting %s' "$1"
3123 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3124 [ -d "$TMP_DIR/rootfs$n/etc" ]
3125 status || cleanup_merge
3127 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3128 action 'Creating %s' "rootfs$p.gz"
3129 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3130 status
3131 done
3132 action 'Creating %s' "rootfs$n.gz"
3133 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3134 status
3135 rm -f $TMP_DIR/iso/boot/rootfs.gz
3136 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3137 create_iso $ISO $TMP_DIR/iso
3138 rm -rf $TMP_DIR
3139 ;;
3142 repack)
3143 # Repack an iso with maximum lzma compression ratio.
3145 ISO=$2
3146 mkdir -p $TMP_DIR/mnt
3148 # Extract filesystems
3149 action 'Mounting %s' "$ISO"
3150 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3151 status || cleanup_merge
3153 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3154 umount -d $TMP_DIR/mnt
3156 for i in $TMP_DIR/iso/boot/rootfs* ; do
3157 action 'Repacking %s' "$(basename $i)"
3158 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3159 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3160 align_to_32bits $i
3161 status
3162 done
3164 create_iso $ISO $TMP_DIR/iso
3165 rm -rf $TMP_DIR
3166 ;;
3169 build-loram)
3170 # Build a Live CD for low RAM systems.
3172 ISO="$2"
3173 OUTPUT="$3"
3174 [ -z "$3" ] && \
3175 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3176 mkdir -p "$TMP_DIR/iso"
3177 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3178 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3179 if ! check_iso_for_loram ; then
3180 umount -d "$TMP_DIR/iso"
3181 die "$ISO is not a valid SliTaz live CD. Abort."
3182 fi
3183 case "$4" in
3184 cdrom) build_loram_cdrom ;;
3185 http) build_loram_http ;;
3186 *) build_loram_ram "$5" ;;
3187 esac
3188 umount $TMP_DIR/iso # no -d: needs /proc
3189 losetup -d $loopdev
3190 rm -rf $TMP_DIR
3191 ;;
3194 emu-iso)
3195 # Emulate an ISO image with Qemu.
3196 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3197 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3198 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3199 echo -e "\nStarting Qemu emulator:\n"
3200 echo -e "qemu $QEMU_OPTS $iso\n"
3201 qemu $QEMU_OPTS $iso
3202 ;;
3205 deduplicate)
3206 # Deduplicate files in a tree
3207 shift
3208 deduplicate "$@"
3209 ;;
3212 usage|*)
3213 # Print usage also for all unknown commands.
3214 usage
3215 ;;
3216 esac
3218 exit 0