tazlito view tazlito @ rev 506

uefi/startup.nsh: hide search loop
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed May 30 15:51:10 2018 +0200 (2018-05-30)
parents 674d4b42127b
children 035c08dd4580
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 resv=$(get 14 "$2/boot/isolinux/efi.img")
315 if [ $(get 57 "$2/boot/isolinux/efi.img" 1) -ne 49 ]; then
316 skiphead=5
317 fatsz=$(get 36 "$2/boot/isolinux/efi.img" 4)
318 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
319 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
320 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
321 else
322 skiphead=4
323 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
324 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
325 fi 2> /dev/null
326 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead='$skiphead' }
327 {
328 if (skiphead!=0) {
329 if ($1=="*") skiphead--
330 next
331 }
332 if (skipdot!=0) {
333 if (skipdot==2) up[cur]=$13 $12
334 else cur=$13 $12
335 skipdot=0
336 next
337 }
338 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
339 if ($3=="2e") skipdot=2
340 else skipdot=1
341 next
342 }
343 if (gotname!=0) {
344 path=""
345 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
346 if (gotname==2) dir[$13 $12]=name
347 else print $1 " " $13 $12 " " path name
348 gotname=0
349 name=""
350 next
351 }
352 if (s!="") {
353 if (eos==0)
354 for (i=2;i<18;i+=2) {
355 if (i==12) i+=2
356 if ($i=="00") break
357 s=s substr($0,i+60,1)
358 }
359 name=s name
360 s=""
361 eos=0
362 next
363 }
364 if ($13=="0f") {
365 s=""
366 for (i=3;i<16;i+=2) {
367 if (i==13) i+=3
368 if ($i=="00") { eos=1; break }
369 s=s substr($0,i+60,1)
370 }
371 next
372 }
373 if ($13=="10") {
374 name=name "/"
375 gotname=2
376 next
377 }
378 if ($13=="20") {
379 gotname=1
380 next
381 }
382 }
383 ' | ( while read offset cluster file; do
384 cluster=$(($(first_block "$2/$file")-$basecluster))
385 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
386 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
387 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
388 done
390 # Update fat12 or fat16
391 get 57 "$2/boot/isolinux/efi.img"
392 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
393 od -An -t u1 -w1 -v
394 ) | awk '
395 {
396 if (state==0) {
397 if ($2=="") {
398 if ($1==12849) fat=12
399 else if ($1==13873) fat=16
400 else fat=32
401 state++
402 }
403 else {
404 for (i=1;i<$2;i++) c[$1+i]=$1+i
405 c[$1+$2]=268435455
406 }
407 next
408 }
409 if (state==1) {
410 prev=$1
411 state++
412 next
413 }
414 if (state==2) {
415 if (fat==12) {
416 n=($1%16)*256+prev
417 if (n!=0) c[pos+1]=n
418 pos++
419 prev=int($1/16)
420 state++
421 next
422 }
423 n=$1*256+prev
424 if (fat==32) {
425 prev=n
426 state=13
427 next
428 }
429 }
430 else if (state==3) {
431 n=$1*16+prev
432 }
433 else if (state==13) {
434 prev=$1*65536+prev
435 state++
436 next
437 }
438 else n=$1*16777216+prev
439 if (n!=0) c[pos+1]=n
440 pos++
441 state=1
442 }
443 END {
444 for (i=1;i<=pos;i+=2) {
445 if (c[i]=="") c[i]=0
446 if (c[i+1]=="") c[i+1]=0
447 if (fat==12) printf "0 %02X %1X%1X %02X |\n",c[i]%256,c[i+1]%16,(c[i]/256)%16,(c[i+1]/16)%256
448 else if (fat==16) printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,c[i+1]%256,(c[i+1]/256)%256
449 else {
450 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
451 printf "0 %02X %02X %02X %02X |\n",c[i+1]%256,(c[i+1]/256)%256,(c[i+1]/65536)%256,(c[i+1]/16777216)%256
452 }
453 }
454 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
455 conv=notrunc bs=512 > /dev/null 2>&1
456 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
457 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
459 # Cleanup cache
460 umount $2
461 mount -o loop,ro $1 $2
462 }
465 # allocate efi.img stub to share EFI files in the EFI boot partition
467 alloc_uefi_part() {
468 local basedir=$(dirname "$1")/..
469 local fclust=$({
470 [ -d $basedir/efi ] &&
471 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
472 while [ -s "$1" ]; do
473 local efifile
474 case "$1" in
475 *taz) efifile=bootia32.efi ;;
476 *taz64) efifile=bootx64.efi ;;
477 esac
478 if [ ! -s $basedir/efi/boot/$efifile ] &&
479 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
480 mkdir -p $basedir/efi/boot 2> /dev/null
481 ln "$1" "$basedir/efi/boot/$(basename $1).efi"
482 stat -c "%s %n" "$1"
483 for i in $basedir/boot/rootfs* ; do
484 ln "$i" $basedir/efi/boot/ &&
485 stat -c "%s %n" "$i"
486 done 2> /dev/null
487 efilinux="/EFI/BOOT/$(basename $1).efi"
488 sed 's|/|\\|g' >> $basedir/efi/boot/startup.nsh <<EOT
489 # start tazlito $efilinux
490 @echo -off
491 set -v num 0
492 for %i run (1 20)
493 if exist FS%num%:$efilinux then
494 echo -on
495 FS%num%:
496 $efilinux rw root=0x100 autologin\
497 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
498 [ "$efifile" == "bootx64.efi" -a -s $basedir/efi/boot/${f}64 ] && \
499 f=${f}64; echo -n " initrd=/EFI/BOOT/$f";done)
500 @echo -off
501 endif
502 set -v num %i
503 endfor
504 # stop tazlito $efilinux
505 EOT
506 fi
507 shift
508 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
509 [ ${fclust:-0} -eq 0 ] && return
510 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
511 BEGIN {
512 FS="/"
513 }
514 NF > 1 {
515 d[NF $NF]+=2
516 d[NF-1 $(NF-1)]+=($NF+25)/13
517 }
518 END {
519 for (i in d)
520 n+=int((d[i]+63)/64)
521 print n
522 }')
523 local clusters=$(($fclust+$dclust))
524 if [ $clusters -lt 4068 ]; then
525 fsect=$(((($clusters+2)*3+1023)/1024))
526 ftype="31 32"
527 fhead="F8 FF FF"
528 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
529 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
530 rootsz=2
531 elif [ $clusters -lt 65525 ]; then
532 fsect=$((($clusters+2+255)/256))
533 ftype="31 36"
534 fhead="F8 FF FF FF"
535 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
536 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
537 rootsz=2
538 else
539 fsect=$((($clusters+2+127)/128))
540 ftype="33 32"
541 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
542 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
543 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
544 rootsz=1
545 fi
546 # reserved + fat*2 + root dir + dirs
547 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
548 s=$((($count+$fclust)*4))
549 if [ $s -gt 65535 ]; then
550 size="00 00"
551 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
552 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
553 else
554 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
555 size32="00 00 00 00"
556 fi
557 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
558 count=$s 2> /dev/null
560 # Create boot sector
561 if [ "$ftype" == "33 32" ]; then
562 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
563 conv=notrunc
564 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
565 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
566 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
567 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
568 0 80 00 29 00 00 00 00 53 59 53 54 45 4d 00 00 00 |
569 0 00 00 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
570 EOT
571 while read ofs data; do
572 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
573 bs=1 seek=$ofs of=$basedir/boot/isolinux/efi.img
574 done <<EOT
575 510 55:aa:52:52:61:41
576 996 72:72:41:61:ff:ff:ff:ff:02
577 1022 55:aa
578 EOT
579 else
580 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
581 seek=510 bs=1 conv=notrunc
582 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
583 conv=notrunc
584 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
585 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
586 0 $size32 80 00 29 00 00 00 00 53 59 53 54 45 |
587 0 4d 20 20 20 20 20 46 41 54 $ftype 20 20 20 cd 18 |
588 0 cd 19 eb fa |
589 EOT
590 fi 2> /dev/null
592 # Create fats
593 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
594 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
595 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
596 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
598 # Add label
599 echo "0 53 59 53 54 45 4d 20 20 20 20 20 08 |" | hexdump -R | \
600 dd of=$basedir/boot/isolinux/efi.img bs=512 conv=notrunc \
601 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
603 mkdir -p /tmp/mnt$$
604 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
605 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
606 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
607 sync
608 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
609 skip=$rsect bs=512 count=$fsect 2> /dev/null
610 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
611 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
612 umount /tmp/mnt$$
613 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
614 seek=$rsect bs=512 conv=notrunc 2> /dev/null
615 rm /tmp/fat$$
616 rmdir /tmp/mnt$$
618 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
619 seek=$count 2> /dev/null
620 }
623 # isolinux.conf doesn't know the kernel version.
624 # We name the kernel image 'bzImage'.
625 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
627 make_bzImage_hardlink() {
628 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
629 rm -f ${1:-.}/bzImage 2>/dev/null
630 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
631 fi
632 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
633 rm -f ${1:-.}/bzImage64 2> /dev/null
634 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
635 fi
636 }
639 create_iso() {
640 cd $2
641 deduplicate
643 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
644 make_bzImage_hardlink $2/boot
645 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
647 cat > /tmp/cdsort$$ <<EOT
648 $PWD/boot/isolinux 100
649 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
650 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
651 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
652 $PWD/boot/isolinux/efi.img 300
653 $PWD/boot/isolinux/isolinux.bin 399
654 $PWD/boot/isolinux/boot.cat 400
655 EOT
657 action 'Computing md5...'
658 touch boot/isolinux/boot.cat
659 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
660 sort -k 2 > md5sum
661 status
663 cd - >/dev/null
664 title 'Generating ISO image'
666 _ 'Generating %s' "$1"
667 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
668 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
669 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
670 -no-emul-boot -boot-load-size 4 -boot-info-table \
671 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
672 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
673 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
674 -A "tazlito $VERSION/$(genisoimage --version)" \
675 -copyright README -P "www.slitaz.org" -no-pad $2
676 rm -f /tmp/cdsort$$
677 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
679 mkdir /tmp/mnt$$
680 mount -o loop,ro $1 /tmp/mnt$$
681 fixup_uefi_part $1 /tmp/mnt$$
682 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
683 ${uefi:+boot/isolinux/efi.img} ; do
684 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
685 done
686 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
687 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
688 umount -d /tmp/mnt$$
689 rmdir /tmp/mnt$$
691 if [ -s '/etc/tazlito/info' ]; then
692 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
693 action 'Storing ISO info...'
694 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
695 status
696 fi
697 fi
699 if [ -x '/usr/bin/isohybrid' ]; then
700 action 'Creating hybrid ISO...'
701 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
702 status
703 fi
705 if [ -x '/usr/bin/iso2exe' ]; then
706 echo 'Creating EXE header...'
707 /usr/bin/iso2exe $1 2>/dev/null
708 fi
709 }
712 # Generate a new ISO image using isolinux.
714 gen_livecd_isolinux() {
715 # Some packages may want to alter iso
716 genisohooks iso
717 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
719 # Set date for boot msg.
720 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
721 DATE=$(date +%Y%m%d)
722 action 'Setting build date to: %s...' "$DATE"
723 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
724 status
725 fi
727 cd $DISTRO
728 create_iso $ISO_NAME.iso $ROOTCD
730 action 'Creating the ISO md5sum...'
731 md5sum $ISO_NAME.iso > $ISO_NAME.md5
732 status
734 separator
735 # Some packages may want to alter final iso
736 genisohooks final
737 }
740 lzma_history_bits() {
741 #
742 # This generates an ISO which boots with Qemu but gives
743 # rootfs errors in frugal or liveUSB mode.
744 #
745 # local n
746 # local sz
747 # n=20 # 1Mb
748 # sz=$(du -sk $1 | cut -f1)
749 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
750 # n=$(( $n + 1 ))
751 # sz=$(( $sz / 2 ))
752 # done
753 # echo $n
754 echo ${LZMA_HISTORY_BITS:-24}
755 }
758 lzma_switches() {
759 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
760 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
761 }
764 lzma_set_size() {
765 # Update size field for lzma'd file packed using -si switch
766 return # Need to fix kernel code?
768 local n i
769 n=$(unlzma < $1 | wc -c)
770 for i in $(seq 1 8); do
771 printf '\\\\x%02X' $(($n & 255))
772 n=$(($n >> 8))
773 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
774 }
777 align_to_32bits() {
778 local size=$(stat -c %s ${1:-/dev/null})
779 [ $((${size:-0} & 3)) -ne 0 ] &&
780 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
781 }
784 dogzip() {
785 gzip -9 > $1
786 [ -x /usr/bin/advdef ] && advdef -qz4 $1
787 }
790 # Pack rootfs
792 pack_rootfs() {
793 ( cd $1; find . -print | cpio -o -H newc ) | \
794 case "$COMPRESSION" in
795 none)
796 _ 'Creating %s without compression...' 'initramfs'
797 cat > $2
798 ;;
799 gzip)
800 _ 'Creating %s with gzip compression...' 'initramfs'
801 dogzip $2
802 ;;
803 *)
804 _ 'Creating %s with lzma compression...' 'initramfs'
805 lzma e -si -so $(lzma_switches $1) > $2
806 lzma_set_size $2
807 ;;
808 esac
809 align_to_32bits $2
810 echo 1 > /tmp/rootfs
811 }
814 # Compression functions for writeiso.
816 write_initramfs() {
817 case "$COMPRESSION" in
818 lzma)
819 _n 'Creating %s with lzma compression...' "$INITRAMFS"
820 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
821 align='y'
822 lzma_set_size "/$INITRAMFS"
823 ;;
824 gzip)
825 _ 'Creating %s with gzip compression...' "$INITRAMFS"
826 cpio -o -H newc | dogzip "/$INITRAMFS"
827 ;;
828 *)
829 # align='y'
830 _ 'Creating %s without compression...' "$INITRAMFS"
831 cpio -o -H newc > "/$INITRAMFS"
832 ;;
833 esac < /tmp/list
834 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
835 echo 1 > /tmp/rootfs
836 }
839 # Deduplicate files (MUST be on the same filesystem).
841 deduplicate() {
842 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
843 (
844 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
845 while read attr inode link file; do
846 [ -L "$file" ] && continue
847 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
848 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
849 rm -f "$file"
850 if ln "$old_file" "$file" 2>/dev/null; then
851 inode="$old_inode"
852 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
853 save="$(($save+(${attr%%-*}+512)/1024))"
854 else
855 cp -a "$old_file" "$file"
856 fi
857 fi
858 fi
859 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
860 done
861 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
862 )
864 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
865 (
866 old_attr=""; hardlinks=0;
867 while read attr inode link file; do
868 attr="${attr/-TARGET-/-$(readlink $file)}"
869 if [ "$attr" == "$old_attr" ]; then
870 if [ "$inode" != "$old_inode" ]; then
871 rm -f "$file"
872 if ln "$old_file" "$file" 2>/dev/null; then
873 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
874 else
875 cp -a "$old_file" "$file"
876 fi
877 fi
878 else
879 old_file="$file"
880 old_attr="$attr"
881 old_inode="$inode"
882 fi
883 done
884 _ '%s duplicate symlinks.' "$hardlinks"
885 )
886 }
889 # Generate a new initramfs from the root filesystem.
891 gen_initramfs() {
892 # Just in case CTRL+c
893 rm -f $DISTRO/gen
895 # Some packages may want to alter rootfs
896 genisohooks rootfs
897 cd $1
899 # Normalize file time
900 find $1 -newer $1 -exec touch -hr $1 {} \;
902 # Link duplicate files
903 deduplicate
905 # Use lzma if installed. Display rootfs size in realtime.
906 rm -f /tmp/rootfs 2>/dev/null
907 pack_rootfs . $DISTRO/$(basename $1).gz &
908 sleep 2
909 echo -en "\nFilesystem size:"
910 while [ ! -f /tmp/rootfs ]; do
911 sleep 1
912 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
913 done
914 echo -e "\n"
915 rm -f /tmp/rootfs
916 cd $DISTRO
917 mv $(basename $1).gz $ROOTCD/boot
918 }
921 distro_sizes() {
922 if [ -n "$start_time" ]; then
923 time=$(($(date +%s) - $start_time))
924 sec=$time
925 div=$(( ($time + 30) / 60))
926 [ "$div" -ne 0 ] && min="~ ${div}m"
927 _ 'Build time : %ss %s' "$sec" "$min"
928 fi
929 cat <<EOT
930 Build date : $(date +%Y%m%d)
931 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
932 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
933 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
934 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
935 EOT
936 footer "Image is ready: $ISO_NAME.iso"
937 }
940 # Print ISO and rootfs size.
942 distro_stats() {
943 title 'Distro statistics: %s' "$DISTRO"
944 distro_sizes
945 }
948 # Create an empty configuration file.
950 empty_config_file() {
951 cat >> tazlito.conf <<"EOF"
952 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
953 #
955 # Name of the ISO image to generate.
956 ISO_NAME=""
958 # ISO image volume name.
959 VOLUM_NAME="SliTaz"
961 # Name of the preparer.
962 PREPARED="$USER"
964 # Path to the packages repository and the packages.list.
965 PACKAGES_REPOSITORY=""
967 # Path to the distro tree to gen-distro from a list of packages.
968 DISTRO=""
970 # Path to the directory containing additional files
971 # to copy into the rootfs and rootcd of the LiveCD.
972 ADDFILES="$DISTRO/addfiles"
974 # Default answer for binary question (Y or N)
975 DEFAULT_ANSWER="ASK"
977 # Compression utility (lzma, gzip or none)
978 COMPRESSION="lzma"
979 EOF
980 }
983 # Extract rootfs.gz somewhere
985 extract_rootfs() {
986 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
987 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
988 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
989 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
990 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
991 }
994 # Extract flavor file to temp directory
996 extract_flavor() {
997 # Input: $1 - flavor name to extract;
998 # $2 = absent/empty: just extract 'outer layer'
999 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1000 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1001 # Output: temp dir path where flavor was extracted
1002 local f="$1.flavor" from to infos="$1.desc"
1003 [ -f "$f" ] || die "File '$f' not found"
1004 local dir="$(mktemp -d)"
1005 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1007 if [ -n "$2" ]; then
1008 cd $dir
1010 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1012 for i in rootcd rootfs; do
1013 [ -f "$1.$i" ] || continue
1014 mkdir "$i"
1015 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1016 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1017 rm "$1.$i"
1018 done
1019 touch -t 197001010100.00 $1.*
1020 # Info to be stored inside ISO
1021 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
1022 rm $1.list*
1024 # Renames
1025 while read from to; do
1026 [ -f "$from" ] || continue
1027 mv "$from" "$to"
1028 done <<EOT
1029 $1.nonfree non-free.list
1030 $1.pkglist packages.list
1031 $1-distro.sh distro.sh
1032 $1.receipt receipt
1033 $1.mirrors mirrors
1034 $1.desc description
1035 EOT
1036 fi
1038 echo $dir
1042 # Pack flavor file from temp directory
1044 pack_flavor() {
1045 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1049 # Remove duplicate files
1051 files_match() {
1052 if [ -d "$1" ]; then
1053 return 1
1055 elif [ -L "$1" ] && [ -L "$2" ]; then
1056 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
1058 elif [ -f "$1" ] && [ -f "$2" ]; then
1059 cmp -s "$1" "$2" && return 0
1061 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
1062 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
1063 return 0
1065 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
1066 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1067 return 0
1069 fi 2> /dev/null
1070 return 1
1073 remove_with_path() {
1074 dir="$(dirname $1)"
1075 rm -f "$1"
1076 while rmdir "$dir" 2> /dev/null; do
1077 dir="$(dirname $dir)"
1078 done
1081 mergefs() {
1082 # Note, many packages have files with spaces in the name
1083 IFS=$'\n'
1085 local size1=$(du -hs "$1" | awk '{ print $1 }')
1086 local size2=$(du -hs "$2" | awk '{ print $1 }')
1087 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1089 # merge symlinks files and devices
1090 ( cd "$1"; find ) | \
1091 while read file; do
1092 files_match "$1/$file" "$2/$file" "$file" &&
1093 remove_with_path "$2/$file"
1094 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1095 done
1097 unset IFS
1098 status
1102 cleanup_merge() {
1103 rm -rf $TMP_DIR
1104 exit 1
1108 # Update isolinux config files for multiple rootfs
1110 update_bootconfig() {
1111 local files
1112 action 'Updating boot config files...'
1113 files="$(grep -l 'include common' $1/*.cfg)"
1114 for file in $files; do
1115 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1116 if (/label/) label=$0;
1117 else if (/kernel/) kernel=$0;
1118 else if (/append/) {
1119 i=index($0,"rootfs.gz");
1120 append=substr($0,i+9);
1122 else if (/include/) {
1123 for (i = 1; i <= n; i++) {
1124 print label i
1125 print kernel;
1126 initrd="initrd=/boot/rootfs" n ".gz"
1127 for (j = n - 1; j >= i; j--) {
1128 initrd=initrd ",/boot/rootfs" j ".gz";
1130 printf "\tappend %s%s\n",initrd,append;
1131 print "";
1133 print;
1135 else print;
1136 }' < $file > $file.$$
1137 mv -f $file.$$ $file
1138 done
1139 sel="$(echo $2 | awk '{
1140 for (i=1; i<=NF; i++)
1141 if (i % 2 == 0) printf " slitaz%d", i/2
1142 else printf " %s", $i
1143 }')"
1145 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1147 label slitaz
1148 kernel /boot/isolinux/ifmem.c32
1149 append$sel noram
1151 label noram
1152 config noram.cfg
1154 EOT
1156 # Update vesamenu
1157 if [ -s "$1/isolinux.cfg" ]; then
1158 files="$files $1/isolinux.cfg"
1159 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1160 BEGIN {
1161 kernel = " COM32 c32box.c32"
1164 if (/ROWS/) print "MENU ROWS " n+$3;
1165 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1166 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1167 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1168 else if (/VSHIFT/) {
1169 x = $3-n;
1170 if (x < 0) x = 0;
1171 print "MENU VSHIFT " x;
1173 else if (/rootfs.gz/) {
1174 linux = "";
1175 if (/bzImage/) linux = "linux /boot/bzImage ";
1176 i = index($0, "rootfs.gz");
1177 append = substr($0, i+9);
1178 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1179 printf "\tappend%s noram\n", sel;
1180 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1181 for (i = 1; i <= n; i++) {
1182 print "LABEL slitaz" i
1183 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1184 printf "%s\n", kernel;
1185 initrd = "initrd=/boot/rootfs" n ".gz"
1186 for (j = n - 1; j >= i; j--) {
1187 initrd = initrd ",/boot/rootfs" j ".gz";
1189 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1192 else if (/bzImage/) kernel = $0;
1193 else print;
1194 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1195 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1196 fi
1198 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1199 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1200 cat > $1/noram.cfg <<EOT
1201 implicit 0
1202 prompt 1
1203 timeout 80
1204 $(grep '^F[0-9]' $1/isolinux.cfg)
1206 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1207 say Not enough RAM to boot slitaz. Trying hacker mode...
1208 default hacker
1209 label hacker
1210 KERNEL /boot/bzImage
1211 append rw root=/dev/null vga=normal
1213 label reboot
1214 EOT
1216 if [ -s $1/c32box.c32 ]; then
1217 cat >> $1/noram.cfg <<EOT
1218 COM32 c32box.c32
1219 append reboot
1221 label poweroff
1222 COM32 c32box.c32
1223 append poweroff
1225 EOT
1226 else
1227 echo " com32 reboot.c32" >> $1/noram.cfg
1228 fi
1230 # Restore real label names
1231 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1232 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1233 while read pat; do
1234 sed -i "s/slitaz$pat/" $files
1235 done
1236 status
1240 # Uncompress rootfs or module to stdout
1242 uncompress() {
1243 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1244 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1248 # Install a missing package
1250 install_package() {
1251 if [ -z "$2" ]; then
1252 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1253 else
1254 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1255 fi
1256 case "$answer" in
1257 y)
1258 # We don't want package on host cache.
1259 action 'Getting and installing package: %s' "$1"
1260 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1261 status ;;
1262 *)
1263 return 1 ;;
1264 esac
1268 # Check iso for loram transformation
1270 check_iso_for_loram() {
1271 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1272 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1276 # Remove duplicated files in $1/efi/boot from $1/boot
1278 cleanup_efi_boot() {
1279 for i in $1/efi/boot/* ; do
1280 [ -f $i ] || continue
1281 b=${i/\/efi\//\/}
1282 cmp $i ${b%.efi} || continue
1283 rm -f $i
1284 case "$i" in
1285 *vmlinuz*) sed -i '/# start tazlito /,/# stop tazlito /d' \
1286 $(dirname $i)/startup.nsh
1287 esac
1288 if [ ! -s $(dirname $i)/startup.nsh ]; then
1289 rm $(dirname $i)/startup.nsh
1290 rmdir $1/efi/boot && rmdir $1/efi
1291 fi
1292 done 2> /dev/null
1296 # Build initial rootfs for loram ISO ram/cdrom/http
1298 build_initfs() {
1299 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1300 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1301 mirror3.slitaz.org mirror.slitaz.org"
1302 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1303 [ -z "$version" ] && die "Can't find the kernel version." \
1304 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1306 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1307 need_lib=false
1308 for i in bin dev run mnt proc tmp sys lib/modules; do
1309 mkdir -p $TMP_DIR/initfs/$i
1310 done
1311 ln -s bin $TMP_DIR/initfs/sbin
1312 ln -s . $TMP_DIR/initfs/usr
1313 for aufs in aufs overlayfs; do
1314 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1315 install_package linux-$aufs $version && break
1316 install_package $aufs $version && break
1317 done || return 1
1318 [ -s /init ] || install_package slitaz-boot-scripts
1319 cp /init $TMP_DIR/initfs/
1320 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1321 $TMP_DIR/initfs/lib/modules
1322 if [ "$1" == 'cdrom' ]; then
1323 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1324 else
1325 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1326 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1327 install_package linux-squashfs $version || return 1
1328 done
1329 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1330 $TMP_DIR/initfs/lib/modules
1331 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1332 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1333 fi
1334 if [ "$1" == 'http' ]; then
1335 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1336 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1337 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1338 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1339 cp -a /dev/fuse $TMP_DIR/initfs/dev
1340 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1341 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1342 else
1343 need_lib=true
1344 fi
1345 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1346 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1347 else
1348 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1349 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1350 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1351 cp -a /lib/librt* $TMP_DIR/initfs/lib
1352 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1353 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1354 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1355 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1356 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1357 need_lib=true
1358 fi
1359 cd $TMP_DIR/fs
1360 echo 'Getting slitaz-release & ethernet modules...'
1361 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1362 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1363 [ -s rootfs* ] || continue
1364 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1365 rm -f rootfs*
1366 done 2>&1 > /dev/null
1367 cd - > /dev/null
1368 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1369 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1370 -type f -name '*.ko*' | while read mod; do
1371 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1372 uncompress $mod > $f
1373 grep -q alias=pci: $f || rm -f $f
1374 done
1375 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1376 f=$(basename $i)..z
1377 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1378 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1379 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1380 for j in $deps; do
1381 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1382 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1383 done
1384 done
1385 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"
1386 _n 'List of URLs to insert: '
1387 read -t 30 urliso2
1388 urliso="$urliso2 $urliso"
1389 fi
1390 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1391 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1392 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1393 else
1394 cp /bin/busybox $TMP_DIR/initfs/bin
1395 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1396 cp /sbin/insmod $TMP_DIR/initfs/bin
1397 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1398 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1399 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1400 fi
1401 need_lib=true
1402 fi
1403 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1404 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1405 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1406 done
1407 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1408 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1409 $TMP_DIR/initfs/lib/modules 2>/dev/null
1410 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1411 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1412 cp -a $i $TMP_DIR/initfs/dev
1413 done
1414 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1415 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1416 cp -a $i $TMP_DIR/initfs/dev
1417 done 2>/dev/null
1418 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1419 cp -a $i $TMP_DIR/initfs/lib
1420 done
1421 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1422 #!/bin/sh
1424 getarg() {
1425 grep -q " \$1=" /proc/cmdline || return 1
1426 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1427 return 0
1430 copy_rootfs() {
1431 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1432 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1433 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1434 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1435 path=/mnt/
1436 return 0
1437 else
1438 rm -f /mnt/rootfs*
1439 return 1
1440 fi
1443 echo "Switching / to tmpfs..."
1444 mount -t proc proc /proc
1445 size="\$(grep rootfssize= < /proc/cmdline | \\
1446 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1447 [ -n "\$size" ] || size="-o size=90%"
1449 mount -t sysfs sysfs /sys
1450 for i in /lib/modules/*.ko ; do
1451 echo -en "Probe \$i \\r"
1452 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1453 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1454 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1455 insmod /lib/modules/\$k.ko 2> /dev/null
1456 done
1457 echo "Loading \$i"
1458 insmod \$i 2> /dev/null
1459 break
1460 done
1461 done
1462 umount /sys
1463 while read var default; do
1464 eval \$var=\$default
1465 getarg \$var \$var
1466 done <<EOT
1467 eth eth0
1468 dns 208.67.222.222,208.67.220.220
1469 netmask 255.255.255.0
1470 gw
1471 ip
1472 EOT
1473 grep -q \$eth /proc/net/dev || sh
1474 if [ -n "\$ip" ]; then
1475 ifconfig \$eth \$ip netmask \$netmask up
1476 route add default gateway \$gw
1477 for i in \$(echo \$dns | sed 's/,/ /g'); do
1478 echo "nameserver \$i" >> /etc/resolv.conf
1479 done
1480 else
1481 udhcpc -f -q -s /lib/udhcpc -i \$eth
1482 fi
1483 for i in $urliso ; do
1484 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1485 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"
1486 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1487 done
1488 getarg urliso URLISO
1489 DIR=fs
1490 if getarg loram DIR; then
1491 DEVICE=\${DIR%,*}
1492 DIR=/\${DIR#*,}
1493 fi
1494 mount -t tmpfs \$size tmpfs /mnt
1495 path2=/mnt/.httpfs/
1496 path=/mnt/.cdrom/
1497 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1498 while [ ! -d \$path/boot ]; do
1499 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1500 httpfs \$i \$path2 && echo \$i && break
1501 done
1502 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1503 done
1505 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1506 umount /proc
1507 branch=:/mnt/.cdrom/\$DIR
1508 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1509 branch=
1510 lp=1
1511 insmod /lib/modules/squashfs.ko 2> /dev/null
1512 for i in \${path}boot/rootfs?.* ; do
1513 fs=\${i#*root}
1514 branch=\$branch:/mnt/.\$fs
1515 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1516 losetup -o 124 /dev/loop\$lp \$i
1517 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1518 lp=\$((\$lp+1))
1519 done
1520 fi
1521 mkdir -p /mnt/.rw/mnt/.httpfs
1522 while read type opt; do
1523 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1524 done <<EOT
1525 aufs br=/mnt/.rw\$branch
1526 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1527 EOT
1528 rm -rf /lib/modules
1529 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1530 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1531 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1532 EOTEOT
1533 chmod +x $TMP_DIR/initfs/init
1534 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1535 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1536 rm -f $i
1537 done 2>/dev/null
1538 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1539 lzma e $TMP_DIR/initfs.gz -si
1540 lzma_set_size $TMP_DIR/initfs.gz
1541 rm -rf $TMP_DIR/initfs
1542 align_to_32bits $TMP_DIR/initfs.gz
1543 return 0
1547 # Move each initramfs to squashfs
1549 build_loram_rootfs() {
1550 rootfs_sizes=""
1551 for i in $TMP_DIR/iso/boot/rootfs*; do
1552 mkdir -p $TMP_DIR/fs
1553 cd $TMP_DIR/fs
1554 uncompress $i | cpio -idm
1555 deduplicate
1556 cd - > /dev/null
1557 rootfs=$TMP_DIR/$(basename $i)
1558 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1559 cd $TMP_DIR
1560 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1561 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1562 rm -f $rootfs
1563 mv $rootfs.cpio $rootfs
1564 cd - > /dev/null
1565 rm -rf $TMP_DIR/fs
1566 done
1570 # Move meta boot configuration files to basic configuration files
1571 # because meta loram flavor is useless when rootfs is not loaded in RAM
1573 unmeta_boot() {
1574 local root=${1:-$TMP_DIR/loramiso}
1575 if [ -f $root/boot/isolinux/noram.cfg ]; then
1576 # We keep enough information to do unloram...
1577 [ -s $root/boot/isolinux/common.cfg ] &&
1578 sed -i 's/label slitaz/label orgslitaz/' \
1579 $root/boot/isolinux/common.cfg
1580 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1581 shift
1582 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1583 $root/boot/isolinux/isolinux.cfg
1584 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1585 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1586 $root/boot/isolinux/*.cfg
1587 fi
1591 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1592 # These squashfs may be loaded in RAM at boot time.
1593 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1594 # Meta flavors are converted to normal flavors.
1596 build_loram_cdrom() {
1597 build_initfs cdrom || return 1
1598 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1599 cleanup_efi_boot $TMP_DIR/loramiso
1600 mkdir $TMP_DIR/loramiso/fs
1601 cd $TMP_DIR/loramiso/fs
1602 for i in $( ls ../boot/root* | sort -r ) ; do
1603 uncompress $i | cpio -idmu
1604 rm -f $i
1605 done
1606 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1607 cd - >/dev/null
1608 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1609 unmeta_boot
1610 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1611 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1612 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1613 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1614 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1615 create_iso $OUTPUT $TMP_DIR/loramiso
1619 # Create http bootstrap to load and remove loram_cdrom
1620 # Meta flavors are converted to normal flavors.
1622 build_loram_http() {
1623 build_initfs http || return 1
1624 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1625 cleanup_efi_boot $TMP_DIR/loramiso
1626 rm -f $TMP_DIR/loramiso/boot/rootfs*
1627 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1628 unmeta_boot
1629 create_iso $OUTPUT $TMP_DIR/loramiso
1633 # Update meta flavor selection sizes.
1634 # Reduce sizes with rootfs gains.
1636 update_metaiso_sizes() {
1637 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1638 do
1639 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1640 local sizes="$rootfs_sizes"
1641 local new
1642 set -- $append
1643 shift
1644 [ "$1" == "ifmem" ] && shift
1645 new=""
1646 while [ -n "$2" ]; do
1647 local s
1648 case "$1" in
1649 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1650 *M) s=$(( ${1%M} * 1024 ));;
1651 *) s=${1%K};;
1652 esac
1653 sizes=${sizes#* }
1654 for i in $sizes ; do
1655 s=$(( $s - $i ))
1656 done
1657 new="$new $s $2"
1658 shift 2
1659 done
1660 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1661 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1662 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1663 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1664 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1665 done
1669 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1670 # Meta flavor selection sizes are updated.
1672 build_loram_ram() {
1673 build_initfs ram || return 1
1674 build_loram_rootfs "$1"
1675 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1676 cleanup_efi_boot $TMP_DIR/loramiso
1677 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1678 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1679 update_metaiso_sizes
1680 create_iso $OUTPUT $TMP_DIR/loramiso
1684 # Remove files installed by packages
1686 find_flavor_rootfs() {
1687 for i in $1/etc/tazlito/*.extract; do
1688 [ -e $i ] || continue
1689 chroot $1 /bin/sh ${i#$1}
1690 done
1692 # Clean hardlinks and files patched by genisofs in /boot
1693 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1694 rm -f $1/boot/$i*
1695 done
1697 # Clean files generated in post_install
1698 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1699 $1/dev/core $1/dev/fd $1/dev/std*
1701 # Verify md5
1702 cat $1$INSTALLED/*/md5sum | \
1703 while read md5 file; do
1704 [ -e "$1$file" ] || continue
1705 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1706 rm -f "$1$file"
1707 done
1709 # Check configuration files
1710 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1711 [ -e $i ] || continue
1712 mkdir /tmp/volatile$$
1713 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1714 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1715 while read file ; do
1716 [ -e "$1/$file" ] || continue
1717 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1718 done
1719 rm -rf /tmp/volatile$$
1720 done
1722 # Remove other files blindly
1723 for i in $1$INSTALLED/*/files.list; do
1724 for file in $(cat "$i"); do
1725 [ "$1$file" -nt "$i" ] && continue
1726 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1727 [ -d "$1$file" ] || rm -f "$1$file"
1728 done
1729 done
1731 # Remove tazpkg files and tmp files
1732 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1733 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1734 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1735 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1736 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1738 # Cleanup directory tree
1739 cd $1
1740 find * -type d | sort -r | while read dir; do
1741 rmdir "$dir" 2>/dev/null
1742 done
1743 cd - > /dev/null
1747 # Get byte(s) from a binary file
1749 get() {
1750 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1754 # Get cpio flavor info from the ISO image
1756 flavordata() {
1757 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1758 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1762 # Restore undigest mirrors
1764 restore_mirrors() {
1765 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1766 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1768 action 'Restoring mirrors...'
1769 if [ -d "$undigest.bak" ]; then
1770 [ -d "$undigest" ] && rm -r "$undigest"
1771 mv "$undigest.bak" "$undigest"
1772 fi
1773 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1774 :; status
1778 # Setup undigest mirrors
1780 setup_mirrors() {
1781 # Setup mirrors in plain system or in chroot (with variable root=)
1782 local mirrorlist="$1" fresh repacked
1783 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1785 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1786 restore_mirrors
1788 _ 'Setting up mirrors for %s...' "$root/"
1789 # Backing up current undigest mirrors and priority
1790 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1791 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1792 rm -rf '/var/www/tazlito/'
1793 mkdir -p '/var/www/tazlito/'
1795 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1796 fresh='/home/slitaz/packages'
1797 if [ -d "$fresh" ]; then
1798 # Setup first undigest mirror
1799 mkdir -p "$undigest/fresh"
1800 echo "$fresh" > "$undigest/fresh/mirror"
1801 echo 'fresh' >> "$priority"
1802 # Rebuild mirror DB if needed
1803 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1804 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1805 tazpkg mkdb "$fresh" --forced --root=''
1806 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1807 fi
1809 # Repacked packages: high priority
1810 repacked="$PACKAGES_REPOSITORY"
1811 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1812 # According to Tazlito setup file (tazlito.conf):
1813 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1814 # or
1815 # WORK_DIR="/home/slitaz"
1816 # and
1817 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1818 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1820 # Setup second undigest mirror
1821 mkdir -p "$undigest/repacked"
1822 echo "$repacked" > "$undigest/repacked/mirror"
1823 echo 'repacked' >> "$priority"
1824 # Rebuild mirror DB if needed
1825 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1826 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1827 tazpkg mkdb "$repacked" --forced --root=''
1828 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1829 fi
1831 # All repositories listed in mirrors list: normal priority
1832 [ -e "$mirrorlist" ] && \
1833 while read mirror; do
1834 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1835 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1836 mkdir -p "$undigest/$mirrorid"
1837 echo "$mirror" > "$undigest/$mirrorid/mirror"
1838 echo "$mirrorid" >> "$priority"
1839 done < "$mirrorlist"
1841 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1843 # Show list of mirrors
1844 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1845 function show(num, name, url) {
1846 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1849 num++;
1850 "cat " db "/undigest/" $0 "/mirror" | getline url;
1851 show(num, $0, url);
1853 END {
1854 num++;
1855 "cat " db "/mirror" | getline url;
1856 show(num, "main", url);
1857 }' "$priority"
1859 tazpkg recharge --quiet >/dev/null
1863 # Get list of 'packages.info' lists using priority
1865 pi_lists() {
1866 local pi
1867 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1868 local priority="$root$LOCALSTATE/priority"
1869 local undigest="$root$LOCALSTATE/undigest"
1872 [ -s "$priority" ] && cat "$priority"
1873 echo 'main'
1874 [ -d "$undigest" ] && ls "$undigest"
1875 } | awk -vun="$undigest/" '
1877 if (arr[$0] != 1) {
1878 arr[$0] = 1;
1879 print un $0 "/packages.info";
1881 }' | sed 's|/undigest/main||' | \
1882 while read pi; do
1883 [ -e "$pi" ] && echo "$pi"
1884 done
1888 # Strip versions from packages list
1890 strip_versions() {
1891 if [ -n "$stripped" ]; then
1892 action 'Consider list %s already stripped' "$(basename "$1")"
1893 status
1894 return 0
1895 fi
1896 action 'Strip versions from list %s...' "$(basename "$1")"
1897 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1898 [ -f "$in_list" ] || die "List '$in_list' not found."
1900 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1901 awk '
1903 if (FILENAME ~ "packages.info") {
1904 # Collect package names
1905 FS = "\t"; pkg[$1] = 1;
1906 } else {
1907 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1908 while (NF > 1 && ! pkg[$0])
1909 NF --;
1910 printf "%s\n", $0;
1912 }' $(pi_lists) "$in_list" > "$tmp_list"
1914 cat "$tmp_list" > "$in_list"
1915 rm "$tmp_list"
1916 status
1920 # Display list of unknown packages (informative)
1922 display_unknown() {
1923 [ -s "$1" ] || return
1924 echo "Unknown packages:" >&2
1925 cat "$1" >&2
1926 rm "$1"
1930 # Display warnings about critical packages absent (informative)
1932 display_warn() {
1933 [ -s "$1" ] || return
1934 echo "Absent critical packages:" >&2
1935 cat "$1" >&2
1936 rm "$1"
1937 echo "Probably ISO image will be unusable."
1941 # Install packages to rootfs
1943 install_list_to_rootfs() {
1944 local list="$1" rootfs="$2" pkg i ii
1945 local undigest="$rootfs/var/lib/tazpkg/undigest"
1947 # initial tazpkg setup in empty rootfs
1948 tazpkg --root=$rootfs >/dev/null 2>&1
1949 # pass current 'mirror' to the rootfs
1950 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1951 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1952 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1953 # link rootfs packages cache to the regular packages cache
1954 rm -r "$rootfs/var/cache/tazpkg"
1955 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1957 setup_mirrors mirrors
1959 # Just in case if flavor doesn't contain "tazlito" package
1960 mkdir -p "$rootfs/etc/tazlito"
1962 newline
1964 # Choose detailed log with --detailed
1965 if [ -n "$detailed" ]; then
1966 while read pkg; do
1967 separator '-'
1968 echo $pkg
1969 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1970 done < $list
1971 separator '='
1972 else
1973 while read pkg; do
1974 action 'Installing package: %s' "$pkg"
1975 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1976 status
1977 done < $list
1978 fi
1979 newline
1981 restore_mirrors
1982 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1983 for i in fresh repacked; do
1984 ii="$undigest/$i"
1985 [ -d "$ii" ] && rm -rf "$ii"
1986 ii="$rootfs/var/lib/tazpkg/priority"
1987 if [ -f "$ii" ]; then
1988 sed -i "/$i/d" "$ii"
1989 [ -s "$ii" ] || rm "$ii"
1990 fi
1991 done
1992 [ -d "$undigest" ] && \
1993 for i in $(find "$undigest" -type f); do
1994 # Remove all undigest PKGDB files but 'mirror'
1995 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1996 done
1997 [ -d "$undigest" ] && \
1998 rmdir --ignore-fail-on-non-empty "$undigest"
2000 # Un-link packages cache
2001 rm "$rootfs/var/cache/tazpkg"
2003 # Clean /var/lib/tazpkg
2004 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2010 ####################
2011 # Tazlito commands #
2012 ####################
2014 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2015 case "$0" in
2016 *reduplicate)
2017 find ${@:-.} ! -type d -links +1 \
2018 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2019 exit 0 ;;
2020 *deduplicate)
2021 deduplicate "$@"
2022 exit 0 ;;
2023 esac
2026 case "$COMMAND" in
2027 stats)
2028 # Tazlito general statistics from the config file.
2030 title 'Tazlito statistics'
2031 optlist "\
2032 Config file : $CONFIG_FILE
2033 ISO name : $ISO_NAME.iso
2034 Volume name : $VOLUM_NAME
2035 Prepared : $PREPARED
2036 Packages repository : $PACKAGES_REPOSITORY
2037 Distro directory : $DISTRO
2038 Additional files : $ADDFILES
2039 " | sed '/: $/d'
2040 footer
2041 ;;
2044 list-addfiles)
2045 # Simple list of additional files in the rootfs
2046 newline
2047 if [ -d "$ADDFILES/rootfs" ]; then
2048 cd $ADDFILES
2049 find rootfs -type f
2050 else
2051 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2052 fi
2053 newline
2054 ;;
2057 gen-config)
2058 # Generate a new config file in the current dir or the specified
2059 # directory by $2.
2061 if [ -n "$2" ]; then
2062 mkdir -p "$2" && cd "$2"
2063 fi
2065 newline
2066 action 'Generating empty tazlito.conf...'
2067 empty_config_file
2068 status
2070 separator
2071 if [ -f 'tazlito.conf' ] ; then
2072 _ 'Configuration file is ready to edit.'
2073 _ 'File location: %s' "$(pwd)/tazlito.conf"
2074 newline
2075 fi
2076 ;;
2079 configure)
2080 # Configure a tazlito.conf config file. Start by getting
2081 # a empty config file and sed it.
2083 if [ -f 'tazlito.conf' ]; then
2084 rm tazlito.conf
2085 else
2086 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2087 'or in the same directory of the file you want to configure.'
2088 cd /etc
2089 fi
2091 empty_config_file
2093 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2095 # ISO name.
2096 echo -n "ISO name : " ; read answer
2097 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2098 # Volume name.
2099 echo -n "Volume name : " ; read answer
2100 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2101 # Packages repository.
2102 echo -n "Packages repository : " ; read answer
2103 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2104 # Distro path.
2105 echo -n "Distro path : " ; read answer
2106 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2107 footer "Config file is ready to use."
2108 echo 'You can now extract an ISO or generate a distro.'
2109 newline
2110 ;;
2113 gen-iso)
2114 # Simply generate a new iso.
2116 check_root
2117 verify_rootcd
2118 gen_livecd_isolinux
2119 distro_stats
2120 ;;
2123 gen-initiso)
2124 # Simply generate a new initramfs with a new iso.
2126 check_root
2127 verify_rootcd
2128 gen_initramfs "$ROOTFS"
2129 gen_livecd_isolinux
2130 distro_stats
2131 ;;
2134 extract-distro|extract-iso)
2135 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2137 check_root
2138 ISO_IMAGE="$2"
2139 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2140 'Example:\n tazlito image.iso /path/target'
2142 # Set the distro path by checking for $3 on cmdline.
2143 TARGET="${3:-$DISTRO}"
2145 # Exit if existing distro is found.
2146 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2147 'Please clean the distro tree or change directory path.'
2149 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2151 # Start to mount the ISO.
2152 action 'Mounting ISO image...'
2153 mkdir -p "$TMP_DIR"
2154 # Get ISO file size.
2155 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2156 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2157 sleep 2
2158 # Prepare target dir, copy the kernel and the rootfs.
2159 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2160 status
2162 action 'Copying the Linux kernel...'
2163 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2164 make_bzImage_hardlink "$TARGET/rootcd/boot"
2165 else
2166 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2167 fi
2168 status
2170 for i in $(ls $TMP_DIR); do
2171 [ "$i" == 'boot' ] && continue
2172 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2173 done
2175 for loader in isolinux syslinux extlinux grub; do
2176 [ -d "$TMP_DIR/boot/$loader" ] || continue
2177 action 'Copying %s files...' "$loader"
2178 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2179 status
2180 done
2182 action 'Copying the rootfs...'
2183 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2184 status
2186 cleanup_efi_boot "$TARGET/rootcd"
2188 # Extract initramfs.
2189 cd "$TARGET/rootfs"
2190 action 'Extracting the rootfs...'
2191 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2192 extract_rootfs "$i" "$TARGET/rootfs"
2193 done
2194 # unpack /usr
2195 for i in etc/tazlito/*.extract; do
2196 [ -f "$i" ] && . $i ../rootcd
2197 done
2198 # Umount and remove temp directory and cd to $TARGET to get stats.
2199 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2200 cd ..
2201 status
2203 newline
2204 separator
2205 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2206 echo "Distro tree : $(pwd)"
2207 echo "Rootfs size : $(du -sh rootfs)"
2208 echo "Rootcd size : $(du -sh rootcd)"
2209 footer
2210 ;;
2213 list-flavors)
2214 # Show available flavors.
2215 list='/etc/tazlito/flavors.list'
2216 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2217 title 'List of flavors'
2218 cat $list
2219 footer
2220 ;;
2223 show-flavor)
2224 # Show flavor descriptions.
2225 set -e
2226 flavor=${2%.flavor}
2227 flv_dir="$(extract_flavor "$flavor")"
2228 desc="$flv_dir/$flavor.desc"
2229 if [ -n "$brief" ]; then
2230 if [ -z "$noheader" ]; then
2231 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2232 separator
2233 fi
2234 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2235 "$(field ISO "$desc")" \
2236 "$(field Rootfs "$desc")" \
2237 "$(field Description "$desc")"
2238 else
2239 separator
2240 cat "$desc"
2241 fi
2242 cleanup
2243 ;;
2246 gen-liveflavor)
2247 # Generate a new flavor from the live system.
2248 FLAVOR=${2%.flavor}
2249 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2251 case "$FLAVOR" in
2252 -?|-h*|--help)
2253 cat <<EOT
2254 SliTaz Live Tool - Version: $VERSION
2256 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2258 $(boldify '<flavor-patch-file> format:')
2259 $(optlist "\
2260 code data
2261 + package to add
2262 - package to remove
2263 ! non-free package to add
2264 ? display message
2265 @ flavor description
2266 ")
2268 $(boldify 'Example:')
2269 $(optlist "\
2270 @ Developer tools for SliTaz maintainers
2271 + slitaz-toolchain
2272 + mercurial
2273 ")
2274 EOT
2275 exit 1
2276 ;;
2277 esac
2278 mv /etc/tazlito/distro-packages.list \
2279 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2280 rm -f distro-packages.list non-free.list 2>/dev/null
2281 tazpkg recharge
2283 DESC=""
2284 [ -n "$3" ] && \
2285 while read action pkg; do
2286 case "$action" in
2287 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2288 -) yes | tazpkg remove $pkg ;;
2289 !) echo $pkg >> non-free.list ;;
2290 @) DESC="$pkg" ;;
2291 \?) echo -en "$pkg"; read action ;;
2292 esac
2293 done < $3
2295 yes '' | tazlito gen-distro
2296 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2297 mv /etc/tazlito/distro-packages.list.$$ \
2298 /etc/tazlito/distro-packages.list 2>/dev/null
2299 ;;
2302 gen-flavor)
2303 # Generate a new flavor from the last ISO image generated
2304 FLAVOR=${2%.flavor}
2305 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2307 title 'Flavor generation'
2308 check_rootfs
2309 FILES="$FLAVOR.pkglist"
2311 action 'Creating file %s...' "$FLAVOR.flavor"
2312 for i in rootcd rootfs; do
2313 if [ -d "$ADDFILES/$i" ] ; then
2314 FILES="$FILES\n$FLAVOR.$i"
2315 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2316 fi
2317 done
2318 status
2320 answer=$(grep -s ^Description $FLAVOR.desc)
2321 answer=${answer#Description : }
2322 if [ -z "$answer" ]; then
2323 echo -n "Description: "
2324 read answer
2325 fi
2327 action 'Compressing flavor %s...' "$FLAVOR"
2328 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2329 echo "Description : $answer" >> $FLAVOR.desc
2330 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2331 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2332 for i in $(ls $ROOTFS$INSTALLED); do
2333 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2334 EXTRAVERSION=""
2335 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2336 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2337 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2338 echo "$i" >> $FLAVOR.nonfree
2339 else
2340 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2341 fi
2342 done
2343 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2344 for i in $LOCALSTATE/undigest/*/mirror ; do
2345 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2346 done
2347 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2348 touch -t 197001010100.00 $FLAVOR.*
2349 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2350 rm $(echo -e $FILES)
2351 status
2353 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2354 ;;
2357 upgrade-flavor)
2358 # Strip versions from pkglist and update estimated numbers in flavor.desc
2359 flavor="${2%.flavor}"
2360 set -e
2361 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2362 set +e
2364 flv_dir="$(extract_flavor "$flavor")"
2366 strip_versions "$flv_dir/$flavor.pkglist"
2368 action 'Updating %s...' "$flavor.desc"
2370 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2371 set -- $(module calc_sizes "$flv_dir" "$flavor")
2372 restore_mirrors >/dev/null
2374 sed -i -e '/Image is ready/d' \
2375 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2376 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2377 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2378 -e "s|\(Packages *:\).*$|\1 $4|" \
2379 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2380 "$flv_dir/$flavor.desc"
2382 pack_flavor "$flv_dir" "$flavor"
2383 status
2384 display_unknown "$flv_dir/err"
2385 display_warn "$flv_dir/warn"
2386 cleanup
2387 ;;
2390 extract-flavor)
2391 # Extract a flavor into $FLAVORS_REPOSITORY
2392 flavor="${2%.flavor}"
2393 set -e
2394 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2395 set +e
2397 action 'Extracting %s...' "$flavor.flavor"
2398 flv_dir="$(extract_flavor "$flavor" full)"
2399 storage="$FLAVORS_REPOSITORY/$flavor"
2401 rm -rf "$storage" 2>/dev/null
2402 mkdir -p "$storage"
2403 cp -a "$flv_dir"/* "$storage"
2404 rm "$storage/description"
2405 status
2407 strip_versions "$storage/packages.list"
2409 cleanup
2410 ;;
2413 pack-flavor)
2414 # Create a flavor from $FLAVORS_REPOSITORY.
2415 flavor=${2%.flavor}
2416 storage="$FLAVORS_REPOSITORY/$flavor"
2418 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2420 action 'Creating flavor %s...' "$flavor"
2421 tmp_dir="$(mktemp -d)"
2423 while read from to; do
2424 [ -s "$storage/$from" ] || continue
2425 cp -a "$storage/$from" "$tmp_dir/$to"
2426 done <<EOT
2427 mirrors $flavor.mirrors
2428 distro.sh $flavor-distro.sh
2429 receipt $flavor.receipt
2430 non-free.list $flavor.nonfree
2431 EOT
2433 # Build the package list.
2434 # It can include a list from another flavor with the keyword @include
2435 if [ -s "$storage/packages.list" ]; then
2436 include=$(grep '^@include' "$storage/packages.list")
2437 if [ -n "$include" ]; then
2438 include=${include#@include }
2439 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2440 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2441 else
2442 echo -e "\nERROR: Can't find include package list from $include\n"
2443 fi
2444 fi
2445 # Generate the final/initial package list
2446 [ -s "$storage/packages.list" ] && \
2447 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2448 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2449 fi
2451 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2452 # Process multi-rootfs flavor
2453 . "$storage/receipt"
2454 set -- $ROOTFS_SELECTION
2455 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2456 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2457 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2459 for i in rootcd rootfs; do
2460 mkdir "$tmp_dir/$i"
2461 # Copy extra files from the first flavor
2462 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2463 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2464 # Overload extra files by meta flavor
2465 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2466 [ -n "$(ls $tmp_dir/$i)" ] &&
2467 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2468 dogzip "$tmp_dir/$flavor.$i"
2469 rm -rf "$tmp_dir/$i"
2470 done
2471 else
2472 # Process plain flavor
2473 for i in rootcd rootfs; do
2474 [ -d "$storage/$i" ] || continue
2475 (cd "$storage/$i";
2476 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2477 done
2478 fi
2480 unset VERSION MAINTAINER ROOTFS_SELECTION
2481 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2482 ROOTFS_SIZE="$1 (estimated)"
2483 INITRAMFS_SIZE="$2 (estimated)"
2484 ISO_SIZE="$3 (estimated)"
2485 PKGNUM="$4"
2486 . "$storage/receipt"
2488 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2489 Flavor : $FLAVOR
2490 Description : $SHORT_DESC
2491 Version : $VERSION
2492 Maintainer : $MAINTAINER
2493 LiveCD RAM size : $FRUGAL_RAM
2494 Rootfs list : $ROOTFS_SELECTION
2495 Build date : $(date '+%Y%m%d at %T')
2496 Packages : $PKGNUM
2497 Rootfs size : $ROOTFS_SIZE
2498 Initramfs size : $INITRAMFS_SIZE
2499 ISO image size : $ISO_SIZE
2500 ================================================================================
2502 EOT
2504 rm -f $tmp_dir/packages.list
2505 pack_flavor "$tmp_dir" "$flavor"
2506 status
2507 display_unknown "$tmp_dir/err"
2508 display_warn "$flv_dir/warn"
2509 cleanup
2510 ;;
2513 get-flavor)
2514 # Get a flavor's files and prepare for gen-distro.
2515 flavor=${2%.flavor}
2516 title 'Preparing %s distro flavor' "$flavor"
2517 set -e
2518 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2519 set +e
2521 action 'Cleaning %s...' "$DISTRO"
2522 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2523 # Clean old files
2524 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2525 [ -f "$i" ] && rm "$i"
2526 done
2527 mkdir -p "$DISTRO"
2528 status
2530 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2532 action 'Extracting flavor %s...' "$flavor.flavor"
2533 flv_dir="$(extract_flavor "$flavor" info)"
2534 cp -a "$flv_dir"/* .
2535 mv packages.list distro-packages.list
2536 mv -f info /etc/tazlito
2537 status
2539 for i in rootcd rootfs; do
2540 if [ -d "$i" ]; then
2541 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2542 fi
2543 done
2545 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2546 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2548 action 'Updating %s...' 'tazlito.conf'
2549 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2550 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2551 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2552 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2553 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2554 status
2556 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2557 cleanup
2558 ;;
2561 iso2flavor)
2562 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2563 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2565 FLAVOR=${3%.flavor}
2566 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2567 mount -o loop,ro $2 $TMP_DIR/iso
2568 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2569 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2570 ! -s $TMP_DIR/flavor/*.desc ]; then
2571 _ 'META flavors are not supported.'
2572 umount -d $TMP_DIR/iso
2573 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2574 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2575 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2576 umount -d $TMP_DIR/iso
2577 else
2578 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2579 uncompress $i | \
2580 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2581 done
2582 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2583 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2584 '/etc/slitaz-release' '/boot/rootfs.gz'
2585 umount -d $TMP_DIR/iso
2586 else
2587 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2588 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2589 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2590 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2591 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2592 umount -d $TMP_DIR/iso
2593 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2594 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2595 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2596 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2597 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2598 < $TMP_DIR/rootfs$INSTALLED.md5
2599 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2600 if [ -s $TMP_DIR/flavor/*desc ]; then
2601 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2602 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2603 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2604 for i in rootfs rootcd ; do
2605 [ -s $TMP_DIR/flavor/*.list$i ] &&
2606 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2607 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2608 done
2609 else
2610 find_flavor_rootfs $TMP_DIR/rootfs
2611 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2612 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2613 for i in rootfs rootcd ; do
2614 [ "$(ls $TMP_DIR/$i)" ] &&
2615 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2616 done
2617 unset VERSION MAINTAINER
2618 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2619 if [ -n "$DESCRIPTION" ]; then
2620 _n 'Flavor version : '; read -t 30 VERSION
2621 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2622 fi
2624 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2625 Flavor : $FLAVOR
2626 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2627 Version : ${VERSION:-1.0}
2628 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2629 LiveCD RAM size : $RAM_SIZE
2630 Build date : $BUILD_DATE
2631 Packages : $PKGCNT
2632 Rootfs size : $ROOTFS_SIZE
2633 Initramfs size : $INITRAMFS_SIZE
2634 ISO image size : $ISO_SIZE
2635 ================================================================================
2637 EOT
2638 longline "Tazlito can't detect each file installed during \
2639 a package post_install. You should extract this flavor (tazlito extract-flavor \
2640 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2641 tree and remove files generated by post_installs.
2642 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2643 repack the flavor (tazlito pack-flavor $FLAVOR)"
2644 fi
2645 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2646 fi
2647 fi
2648 rm -rf $TMP_DIR
2649 ;;
2652 gen-distro)
2653 # Generate a live distro tree with a set of packages.
2655 check_root
2656 start_time=$(date +%s)
2658 # Tazlito options: --iso or --cdrom
2659 CDROM=''
2660 [ -n "$iso" ] && CDROM="-o loop $iso"
2661 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2663 # Check if a package list was specified on cmdline.
2664 if [ -f "$2" ]; then
2665 LIST_NAME="$2"
2666 else
2667 LIST_NAME='distro-packages.list'
2668 fi
2670 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2671 'Please clean the distro tree or change directory path.'
2672 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2673 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2675 # If list not given: build list with all installed packages
2676 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2677 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2678 fi
2680 # Exit if no list name.
2681 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2683 # Start generation.
2684 title 'Tazlito generating a distro'
2686 # Misc checks
2687 mkdir -p "$PACKAGES_REPOSITORY"
2688 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2689 newline
2691 # Mount CD-ROM to be able to repack boot-loader packages
2692 if [ ! -e /boot -a -n "$CDROM" ]; then
2693 mkdir $TMP_MNT
2694 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2695 ln -s "$TMP_MNT/boot" /
2696 if [ ! -d "$ADDFILES/rootcd" ] ; then
2697 mkdir -p "$ADDFILES/rootcd"
2698 for i in $(ls $TMP_MNT); do
2699 [ "$i" == 'boot' ] && continue
2700 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2701 done
2702 fi
2703 else
2704 rmdir "$TMP_MNT"
2705 fi
2706 fi
2708 # Rootfs stuff.
2709 echo 'Preparing the rootfs directory...'
2710 mkdir -p "$ROOTFS"
2711 export root="$ROOTFS"
2712 # pass current 'mirror' to the root
2713 mkdir -p $root/var/lib/tazpkg $root/etc
2714 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2715 cp -f /etc/slitaz-release $root/etc/slitaz-release
2716 strip_versions "$LIST_NAME"
2718 if [ "$REPACK" == 'y' ]; then
2719 # Determine full packages list with all dependencies
2720 tmp_dir="$(mktemp -d)"
2721 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2722 touch "$tmp_dir/full.pkglist"
2723 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2725 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2726 while read pkgname pkgver; do
2727 # Is package in full list?
2728 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2729 # Is package already repacked?
2730 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2731 _ 'Repacking %s...' "$pkgname-$pkgver"
2732 tazpkg repack "$pkgname" --quiet
2733 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2734 status
2735 done
2737 rm -r "$tmp_dir"
2738 fi
2740 if [ -f non-free.list ]; then
2741 # FIXME: working in the ROOTFS chroot?
2742 newline
2743 echo 'Preparing non-free packages...'
2744 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2745 for pkg in $(cat 'non-free.list'); do
2746 if [ ! -d "$INSTALLED/$pkg" ]; then
2747 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2748 tazpkg get-install get-$pkg
2749 fi
2750 get-$pkg "$ROOTFS"
2751 fi
2752 tazpkg repack $pkg
2753 pkg=$(ls $pkg*.tazpkg)
2754 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2755 mv $pkg $PACKAGES_REPOSITORY
2756 done
2757 fi
2758 cp $LIST_NAME $DISTRO/distro-packages.list
2759 newline
2761 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2763 cd $DISTRO
2764 cp distro-packages.list $ROOTFS/etc/tazlito
2765 # Copy all files from $ADDFILES/rootfs to the rootfs.
2766 if [ -d "$ADDFILES/rootfs" ] ; then
2767 action 'Copying addfiles content to the rootfs...'
2768 cp -a $ADDFILES/rootfs/* $ROOTFS
2769 status
2770 fi
2772 action 'Root filesystem is generated...'; status
2774 # Root CD part.
2775 action 'Preparing the rootcd directory...'
2776 mkdir -p $ROOTCD
2777 status
2779 # Move the boot dir with the Linux kernel from rootfs.
2780 # The efi & boot dirs go directly on the CD.
2781 if [ -d "$ROOTFS/efi" ] ; then
2782 action 'Moving the efi directory...'
2783 mv $ROOTFS/efi $ROOTCD
2784 status
2785 fi
2786 if [ -d "$ROOTFS/boot" ] ; then
2787 action 'Moving the boot directory...'
2788 mv $ROOTFS/boot $ROOTCD
2789 status
2790 fi
2791 cd $DISTRO
2792 # Copy all files from $ADDFILES/rootcd to the rootcd.
2793 if [ -d "$ADDFILES/rootcd" ] ; then
2794 action 'Copying addfiles content to the rootcd...'
2795 cp -a $ADDFILES/rootcd/* $ROOTCD
2796 status
2797 fi
2798 # Execute the distro script used to perform tasks in the rootfs
2799 # before compression. Give rootfs path in arg
2800 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2801 if [ -x "$DISTRO_SCRIPT" ]; then
2802 echo 'Executing distro script...'
2803 sh $DISTRO_SCRIPT $DISTRO
2804 fi
2806 # Execute the custom_rules() found in receipt.
2807 if [ -s "$TOP_DIR/receipt" ]; then
2808 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2809 echo -e "Executing: custom_rules()\n"
2810 . "$TOP_DIR/receipt"
2811 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2812 fi
2813 fi
2815 # Multi-rootfs
2816 if [ -s /etc/tazlito/rootfs.list ]; then
2818 FLAVOR_LIST="$(awk '{
2819 for (i = 2; i <= NF; i+=2)
2820 printf "%s ", $i;
2821 }' /etc/tazlito/rootfs.list)"
2823 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2824 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2825 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2827 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2828 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2829 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2830 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2832 n=0
2833 last=$ROOTFS
2834 while read flavor; do
2835 n=$(($n+1))
2836 mkdir ${ROOTFS}0$n
2837 export root="${ROOTFS}0$n"
2838 # initial tazpkg setup in empty rootfs
2839 tazpkg --root=$root >/dev/null 2>&1
2841 newline
2842 boldify "Building $flavor rootfs..."
2844 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2845 cp "$TOP_DIR/$flavor.flavor" .
2847 if [ ! -s "$flavor.flavor" ]; then
2848 # We may have it in $FLAVORS_REPOSITORY
2849 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2850 tazlito pack-flavor $flavor
2851 else
2852 download $flavor.flavor
2853 fi
2854 fi
2856 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2857 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2858 cp $flavor.pkglist $DISTRO/list-packages0$n
2859 status
2861 strip_versions "$DISTRO/list-packages0$n"
2863 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2865 action 'Updating the boot directory...'
2866 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2867 rm -rf ${ROOTFS}0$n/boot
2869 cd $DISTRO
2870 if [ -s $flavor.rootfs ]; then
2871 _n 'Adding %s rootfs extra files...' "$flavor"
2872 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2873 fi
2875 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2876 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2877 status
2879 rm -f $flavor.flavor install-list
2880 mergefs ${ROOTFS}0$n $last
2881 last=${ROOTFS}0$n
2882 done <<EOT
2883 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2884 EOT
2885 #'
2886 i=$(($n+1))
2887 while [ $n -gt 0 ]; do
2888 mv ${ROOTFS}0$n ${ROOTFS}$i
2889 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2890 gen_initramfs ${ROOTFS}$i
2891 n=$(($n-1))
2892 i=$(($i-1))
2893 export LZMA_HISTORY_BITS=26
2894 done
2895 mv $ROOTFS ${ROOTFS}$i
2896 gen_initramfs ${ROOTFS}$i
2897 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2898 ROOTFS=${ROOTFS}1
2899 else
2900 # Initramfs and ISO image stuff.
2901 gen_initramfs $ROOTFS
2902 fi
2903 gen_livecd_isolinux
2904 distro_stats
2905 cleanup
2906 ;;
2909 clean-distro)
2910 # Remove old distro tree.
2912 check_root
2913 title 'Cleaning: %s' "$DISTRO"
2914 if [ -d "$DISTRO" ] ; then
2915 if [ -d "$ROOTFS" ] ; then
2916 action 'Removing the rootfs...'
2917 rm -f $DISTRO/$INITRAMFS
2918 rm -rf $ROOTFS
2919 status
2920 fi
2921 if [ -d "$ROOTCD" ] ; then
2922 action 'Removing the rootcd...'
2923 rm -rf $ROOTCD
2924 status
2925 fi
2926 action 'Removing eventual ISO image...'
2927 rm -f $DISTRO/$ISO_NAME.iso
2928 rm -f $DISTRO/$ISO_NAME.md5
2929 status
2930 fi
2931 footer
2932 ;;
2935 check-distro)
2936 # Check for a few LiveCD needed files not installed by packages.
2938 # TODO: Remove this function.
2939 # First two files are maintained by tazpkg while it runs on rootfs,
2940 # while last one file should be maintained by tazlito itself.
2941 check_rootfs
2942 title 'Checking distro: %s' "$ROOTFS"
2943 # SliTaz release info.
2944 rel='/etc/slitaz-release'
2945 if [ ! -f "$ROOTFS$rel" ]; then
2946 _ 'Missing release info: %s' "$rel"
2947 else
2948 action 'Release : %s' "$(cat $ROOTFS$rel)"
2949 status
2950 fi
2951 # Tazpkg mirror.
2952 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2953 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2954 todomsg
2955 else
2956 action 'Mirror configuration exists...'
2957 status
2958 fi
2959 # Isolinux msg
2960 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2961 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2962 todomsg
2963 else
2964 action 'Isolinux message seems good...'
2965 status
2966 fi
2967 footer
2968 ;;
2971 writeiso)
2972 # Writefs to ISO image including /home unlike gen-distro we don't use
2973 # packages to generate a rootfs, we build a compressed rootfs with all
2974 # the current filesystem similar to 'tazusb writefs'.
2976 DISTRO='/home/slitaz/distro'
2977 ROOTCD="$DISTRO/rootcd"
2978 COMPRESSION="${2:-none}"
2979 ISO_NAME="${3:-slitaz}"
2980 check_root
2981 # Start info
2982 title 'Write filesystem to ISO'
2983 longline "The command writeiso will write the current filesystem into a \
2984 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2985 newline
2986 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2988 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2989 # Save some space
2990 rm -rf /var/cache/tazpkg/*
2991 rm -f /var/lib/tazpkg/*.bak
2992 rm -rf $DISTRO
2994 # Optionally remove sound card selection and screen resolution.
2995 if [ -z $LaunchedByTazpanel ]; then
2996 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2997 case $anser in
2998 y)
2999 action 'Removing current sound card and screen configurations...'
3000 rm -f /var/lib/sound-card-driver
3001 rm -f /var/lib/alsa/asound.state
3002 rm -f /etc/X11/xorg.conf ;;
3003 *)
3004 action 'Keeping current sound card and screen configurations...' ;;
3005 esac
3006 status
3007 newline
3009 # Optionally remove i18n settings
3010 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3011 case $anser in
3012 y)
3013 action 'Removing current locale/keymap settings...'
3014 newline > /etc/locale.conf
3015 newline > /etc/keymap.conf ;;
3016 *)
3017 action 'Keeping current locale/keymap settings...' ;;
3018 esac
3019 status
3020 fi
3022 # Clean-up files by default
3023 newline > /etc/udev/rules.d/70-persistent-net.rules
3024 newline > /etc/udev/rules.d/70-persistant-cd.rules
3026 # Create list of files including default user files since it is defined in /etc/passwd
3027 # and some new users might have been added.
3028 cd /
3029 echo 'init' > /tmp/list
3030 for dir in bin etc sbin var dev lib root usr home opt; do
3031 [ -d $dir ] && find $dir
3032 done >> /tmp/list
3034 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3035 [ -d $dir ] && echo $dir
3036 done >> /tmp/list
3038 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3040 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3041 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3042 #fi
3043 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3044 touch /var/log/wtmp
3046 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3047 sed -i "/var\/log\/$removelog/d" /tmp/list
3048 done
3050 # Generate initramfs with specified compression and display rootfs
3051 # size in realtime.
3052 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3054 write_initramfs &
3055 sleep 2
3056 cd - > /dev/null
3057 echo -en "\nFilesystem size:"
3058 while [ ! -f /tmp/rootfs ]; do
3059 sleep 1
3060 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3061 done
3062 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3063 echo -e "\n"
3064 rm -f /tmp/rootfs
3066 # Move freshly generated rootfs to the cdrom.
3067 mkdir -p $ROOTCD/boot
3068 mv -f /$INITRAMFS $ROOTCD/boot
3069 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3071 # Now we need the kernel and isolinux files.
3072 copy_from_cd() {
3073 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3074 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3075 unmeta_boot $ROOTCD
3076 umount /media/cdrom
3079 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3080 copy_from_cd;
3081 elif mount | grep /media/cdrom; then
3082 copy_from_cd;
3083 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3084 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3085 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3086 else
3087 touch /tmp/.write-iso-error
3088 longline "When SliTaz is running in RAM the kernel and bootloader \
3089 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3090 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3091 echo -en "----\nENTER to continue..."; read i
3092 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3093 copy_from_cd
3094 fi
3096 # Generate the iso image.
3097 touch /tmp/.write-iso
3098 newline
3099 cd $DISTRO
3100 create_iso $ISO_NAME.iso $ROOTCD
3101 action 'Creating the ISO md5sum...'
3102 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3103 status
3105 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3106 rm -f /tmp/.write-iso
3108 if [ -z $LaunchedByTazpanel ]; then
3109 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3110 case $anser in
3111 y)
3112 umount /dev/cdrom 2>/dev/null
3113 eject
3114 echo -n "Please insert a blank CD-ROM and press ENTER..."
3115 read i && sleep 2
3116 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3117 echo -en "----\nENTER to continue..."; read i ;;
3118 *)
3119 exit 0 ;;
3120 esac
3121 fi
3122 ;;
3125 burn-iso)
3126 # Guess CD-ROM device, ask user and burn the ISO.
3128 check_root
3129 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3130 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3131 # We can specify an alternative ISO from the cmdline.
3132 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3133 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3135 title 'Tazlito burn ISO'
3136 echo "CD-ROM device : /dev/$DRIVE_NAME"
3137 echo "Drive speed : $DRIVE_SPEED"
3138 echo "ISO image : $iso"
3139 footer
3141 case $(yesorno 'Burn ISO image?' 'n') in
3142 y)
3143 title 'Starting Wodim to burn the ISO...'
3144 sleep 2
3145 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3146 footer 'ISO image is burned to CD-ROM.'
3147 ;;
3148 *)
3149 die 'Exiting. No ISO burned.'
3150 ;;
3151 esac
3152 ;;
3155 merge)
3156 # Merge multiple rootfs into one iso.
3158 if [ -z "$2" ]; then
3159 cat <<EOT
3160 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3162 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3163 i.e: rootfsN is a subset of rootfsN-1
3164 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3165 The boot loader will select the rootfs according to the RAM size detected.
3167 Example:
3168 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3170 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3171 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3173 EOT
3174 exit 2
3175 fi
3177 shift # skip merge
3178 append="$1 slitaz1"
3179 shift # skip size1
3180 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3182 ISO=$1.merged
3184 # Extract filesystems
3185 action 'Mounting %s' "$1"
3186 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3187 status || cleanup_merge
3189 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3190 make_bzImage_hardlink $TMP_DIR/iso/boot
3191 umount -d $TMP_DIR/mnt
3192 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3193 _ '%s is already a merged iso. Aborting.' "$1"
3194 cleanup_merge
3195 fi
3196 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3197 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3198 if [ ! -f /boot/isolinux/ifmem.c32 -a
3199 ! -f /boot/isolinux/c32box.c32 ]; then
3200 cat <<EOT
3201 No file /boot/isolinux/ifmem.c32
3202 Please install syslinux package !
3203 EOT
3204 rm -rf $TMP_DIR
3205 exit 1
3206 fi
3207 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3208 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3209 fi
3211 action 'Extracting %s' 'iso/rootfs.gz'
3212 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3213 [ -d $TMP_DIR/rootfs1/etc ]
3214 status || cleanup_merge
3216 n=1
3217 while [ -n "$2" ]; do
3218 shift # skip rootfs N-1
3219 p=$n
3220 n=$(($n + 1))
3221 append="$append $1 slitaz$n"
3222 shift # skip size N
3223 mkdir -p $TMP_DIR/rootfs$n
3225 action 'Extracting %s' "$1"
3226 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3227 [ -d "$TMP_DIR/rootfs$n/etc" ]
3228 status || cleanup_merge
3230 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3231 action 'Creating %s' "rootfs$p.gz"
3232 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3233 status
3234 done
3235 action 'Creating %s' "rootfs$n.gz"
3236 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3237 status
3238 rm -f $TMP_DIR/iso/boot/rootfs.gz
3239 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3240 create_iso $ISO $TMP_DIR/iso
3241 rm -rf $TMP_DIR
3242 ;;
3245 repack)
3246 # Repack an iso with maximum lzma compression ratio.
3248 ISO=$2
3249 mkdir -p $TMP_DIR/mnt
3251 # Extract filesystems
3252 action 'Mounting %s' "$ISO"
3253 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3254 status || cleanup_merge
3256 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3257 umount -d $TMP_DIR/mnt
3259 for i in $TMP_DIR/iso/boot/rootfs* ; do
3260 action 'Repacking %s' "$(basename $i)"
3261 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3262 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3263 align_to_32bits $i
3264 status
3265 done
3267 create_iso $ISO $TMP_DIR/iso
3268 rm -rf $TMP_DIR
3269 ;;
3272 build-loram)
3273 # Build a Live CD for low RAM systems.
3275 ISO="$2"
3276 OUTPUT="$3"
3277 [ -z "$3" ] && \
3278 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3279 mkdir -p "$TMP_DIR/iso"
3280 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3281 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3282 if ! check_iso_for_loram ; then
3283 umount -d "$TMP_DIR/iso"
3284 die "$ISO is not a valid SliTaz live CD. Abort."
3285 fi
3286 case "$4" in
3287 cdrom) build_loram_cdrom ;;
3288 http) build_loram_http ;;
3289 *) build_loram_ram "$5" ;;
3290 esac
3291 umount $TMP_DIR/iso # no -d: needs /proc
3292 losetup -d $loopdev
3293 rm -rf $TMP_DIR
3294 ;;
3297 emu-iso)
3298 # Emulate an ISO image with Qemu.
3299 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3300 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3301 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3302 echo -e "\nStarting Qemu emulator:\n"
3303 echo -e "qemu $QEMU_OPTS $iso\n"
3304 qemu $QEMU_OPTS $iso
3305 ;;
3308 deduplicate)
3309 # Deduplicate files in a tree
3310 shift
3311 deduplicate "$@"
3312 ;;
3315 usage|*)
3316 # Print usage also for all unknown commands.
3317 usage
3318 ;;
3319 esac
3321 exit 0