tazlito view tazlito @ rev 502

Do not scan FS0: only for UEFI boot
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed May 23 22:58:25 2018 +0200 (2018-05-23)
parents 42bc92a7487a
children 8ebd772b1e4d
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 for i in "$1" $basedir/boot/rootfs* ; do
482 ln "$i" $basedir/efi/boot/ &&
483 stat -c "%s %n" "$i"
484 done 2> /dev/null
485 efilinux="/EFI/BOOT/$(basename $1)"
486 eficmdline="$efilinux rw root=0x100 autologin\
487 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
488 [ "$efifile" == "bootx64.efi" -a -s $basedir/efi/boot/${f}64 ] && \
489 f=${f}64; echo -n " initrd=/EFI/BOOT/$f";done)"
490 sed 's|/|\\|g' >> $basedir/efi/boot/startup.nsh <<EOT
491 for %i run (1 10)
492 set -v num %i
493 if exist FS%num%:$efilinux then
494 FS%num%:
495 $eficmdline
496 endif
497 endfor
498 if exist FS0:$efilinux then
499 FS0:
500 $eficmdline
501 endif
502 EOT
503 fi
504 shift
505 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
506 [ ${fclust:-0} -eq 0 ] && return
507 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
508 BEGIN {
509 FS="/"
510 }
511 NF > 1 {
512 d[NF $NF]+=2
513 d[NF-1 $(NF-1)]+=($NF+25)/13
514 }
515 END {
516 for (i in d)
517 n+=int((d[i]+63)/64)
518 print n
519 }')
520 local clusters=$(($fclust+$dclust))
521 if [ $clusters -lt 4068 ]; then
522 fsect=$(((($clusters+2)*3+1023)/1024))
523 ftype="31 32"
524 fhead="F8 FF FF"
525 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
526 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
527 rootsz=2
528 elif [ $clusters -lt 65525 ]; then
529 fsect=$((($clusters+2+255)/256))
530 ftype="31 36"
531 fhead="F8 FF FF FF"
532 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
533 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
534 rootsz=2
535 else
536 fsect=$((($clusters+2+127)/128))
537 ftype="33 32"
538 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
539 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
540 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
541 rootsz=1
542 fi
543 # reserved + fat*2 + root dir + dirs
544 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
545 s=$((($count+$fclust)*4))
546 if [ $s -gt 65535 ]; then
547 size="00 00"
548 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
549 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
550 else
551 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
552 size32="00 00 00 00"
553 fi
554 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
555 count=$s 2> /dev/null
557 # Create boot sector
558 if [ "$ftype" == "33 32" ]; then
559 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
560 conv=notrunc
561 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
562 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
563 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
564 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
565 0 80 00 29 00 00 00 00 53 59 53 54 45 4d 00 00 00 |
566 0 00 00 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
567 EOT
568 while read ofs data; do
569 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
570 bs=1 seek=$ofs of=$basedir/boot/isolinux/efi.img
571 done <<EOT
572 510 55:aa:52:52:61:41
573 996 72:72:41:61:ff:ff:ff:ff:02
574 1022 55:aa
575 EOT
576 else
577 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
578 seek=510 bs=1 conv=notrunc
579 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
580 conv=notrunc
581 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
582 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
583 0 $size32 80 00 29 00 00 00 00 53 59 53 54 45 |
584 0 4d 20 20 20 20 20 46 41 54 $ftype 20 20 20 cd 18 |
585 0 cd 19 eb fa |
586 EOT
587 fi 2> /dev/null
589 # Create fats
590 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
591 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
592 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
593 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
595 # Add label
596 echo "0 53 59 53 54 45 4d 20 20 20 20 20 08 |" | hexdump -R | \
597 dd of=$basedir/boot/isolinux/efi.img bs=512 conv=notrunc \
598 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
600 mkdir -p /tmp/mnt$$
601 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
602 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
603 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
604 sync
605 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
606 skip=$rsect bs=512 count=$fsect 2> /dev/null
607 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
608 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
609 umount /tmp/mnt$$
610 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
611 seek=$rsect bs=512 conv=notrunc 2> /dev/null
612 rm /tmp/fat$$
613 rmdir /tmp/mnt$$
615 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
616 seek=$count 2> /dev/null
617 }
620 # isolinux.conf doesn't know the kernel version.
621 # We name the kernel image 'bzImage'.
622 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
624 make_bzImage_hardlink() {
625 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
626 rm -f ${1:-.}/bzImage 2>/dev/null
627 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
628 fi
629 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
630 rm -f ${1:-.}/bzImage64 2> /dev/null
631 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
632 fi
633 }
636 create_iso() {
637 cd $2
638 deduplicate
640 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
641 make_bzImage_hardlink $2/boot
642 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
644 cat > /tmp/cdsort$$ <<EOT
645 $PWD/boot/isolinux 100
646 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
647 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
648 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
649 $PWD/boot/isolinux/efi.img 300
650 $PWD/boot/isolinux/isolinux.bin 399
651 $PWD/boot/isolinux/boot.cat 400
652 EOT
654 action 'Computing md5...'
655 touch boot/isolinux/boot.cat
656 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
657 sort -k 2 > md5sum
658 status
660 cd - >/dev/null
661 title 'Generating ISO image'
663 _ 'Generating %s' "$1"
664 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
665 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
666 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
667 -no-emul-boot -boot-load-size 4 -boot-info-table \
668 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
669 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
670 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
671 -A "tazlito $VERSION/$(genisoimage --version)" \
672 -copyright README -P "www.slitaz.org" -no-pad $2
673 rm -f /tmp/cdsort$$
674 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
676 mkdir /tmp/mnt$$
677 mount -o loop,ro $1 /tmp/mnt$$
678 fixup_uefi_part $1 /tmp/mnt$$
679 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
680 ${uefi:+boot/isolinux/efi.img} ; do
681 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
682 done
683 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
684 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
685 umount -d /tmp/mnt$$
686 rmdir /tmp/mnt$$
688 if [ -s '/etc/tazlito/info' ]; then
689 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
690 action 'Storing ISO info...'
691 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
692 status
693 fi
694 fi
696 if [ -x '/usr/bin/isohybrid' ]; then
697 action 'Creating hybrid ISO...'
698 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
699 status
700 fi
702 if [ -x '/usr/bin/iso2exe' ]; then
703 echo 'Creating EXE header...'
704 /usr/bin/iso2exe $1 2>/dev/null
705 fi
706 }
709 # Generate a new ISO image using isolinux.
711 gen_livecd_isolinux() {
712 # Some packages may want to alter iso
713 genisohooks iso
714 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
716 # Set date for boot msg.
717 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
718 DATE=$(date +%Y%m%d)
719 action 'Setting build date to: %s...' "$DATE"
720 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
721 status
722 fi
724 cd $DISTRO
725 create_iso $ISO_NAME.iso $ROOTCD
727 action 'Creating the ISO md5sum...'
728 md5sum $ISO_NAME.iso > $ISO_NAME.md5
729 status
731 separator
732 # Some packages may want to alter final iso
733 genisohooks final
734 }
737 lzma_history_bits() {
738 #
739 # This generates an ISO which boots with Qemu but gives
740 # rootfs errors in frugal or liveUSB mode.
741 #
742 # local n
743 # local sz
744 # n=20 # 1Mb
745 # sz=$(du -sk $1 | cut -f1)
746 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
747 # n=$(( $n + 1 ))
748 # sz=$(( $sz / 2 ))
749 # done
750 # echo $n
751 echo ${LZMA_HISTORY_BITS:-24}
752 }
755 lzma_switches() {
756 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
757 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
758 }
761 lzma_set_size() {
762 # Update size field for lzma'd file packed using -si switch
763 return # Need to fix kernel code?
765 local n i
766 n=$(unlzma < $1 | wc -c)
767 for i in $(seq 1 8); do
768 printf '\\\\x%02X' $(($n & 255))
769 n=$(($n >> 8))
770 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
771 }
774 align_to_32bits() {
775 local size=$(stat -c %s ${1:-/dev/null})
776 [ $((${size:-0} & 3)) -ne 0 ] &&
777 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
778 }
781 dogzip() {
782 gzip -9 > $1
783 [ -x /usr/bin/advdef ] && advdef -qz4 $1
784 }
787 # Pack rootfs
789 pack_rootfs() {
790 ( cd $1; find . -print | cpio -o -H newc ) | \
791 case "$COMPRESSION" in
792 none)
793 _ 'Creating %s without compression...' 'initramfs'
794 cat > $2
795 ;;
796 gzip)
797 _ 'Creating %s with gzip compression...' 'initramfs'
798 dogzip $2
799 ;;
800 *)
801 _ 'Creating %s with lzma compression...' 'initramfs'
802 lzma e -si -so $(lzma_switches $1) > $2
803 lzma_set_size $2
804 ;;
805 esac
806 align_to_32bits $2
807 echo 1 > /tmp/rootfs
808 }
811 # Compression functions for writeiso.
813 write_initramfs() {
814 case "$COMPRESSION" in
815 lzma)
816 _n 'Creating %s with lzma compression...' "$INITRAMFS"
817 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
818 align='y'
819 lzma_set_size "/$INITRAMFS"
820 ;;
821 gzip)
822 _ 'Creating %s with gzip compression...' "$INITRAMFS"
823 cpio -o -H newc | dogzip "/$INITRAMFS"
824 ;;
825 *)
826 # align='y'
827 _ 'Creating %s without compression...' "$INITRAMFS"
828 cpio -o -H newc > "/$INITRAMFS"
829 ;;
830 esac < /tmp/list
831 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
832 echo 1 > /tmp/rootfs
833 }
836 # Deduplicate files (MUST be on the same filesystem).
838 deduplicate() {
839 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
840 (
841 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
842 while read attr inode link file; do
843 [ -L "$file" ] && continue
844 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
845 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
846 rm -f "$file"
847 if ln "$old_file" "$file" 2>/dev/null; then
848 inode="$old_inode"
849 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
850 save="$(($save+(${attr%%-*}+512)/1024))"
851 else
852 cp -a "$old_file" "$file"
853 fi
854 fi
855 fi
856 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
857 done
858 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
859 )
861 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
862 (
863 old_attr=""; hardlinks=0;
864 while read attr inode link file; do
865 attr="${attr/-TARGET-/-$(readlink $file)}"
866 if [ "$attr" == "$old_attr" ]; then
867 if [ "$inode" != "$old_inode" ]; then
868 rm -f "$file"
869 if ln "$old_file" "$file" 2>/dev/null; then
870 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
871 else
872 cp -a "$old_file" "$file"
873 fi
874 fi
875 else
876 old_file="$file"
877 old_attr="$attr"
878 old_inode="$inode"
879 fi
880 done
881 _ '%s duplicate symlinks.' "$hardlinks"
882 )
883 }
886 # Generate a new initramfs from the root filesystem.
888 gen_initramfs() {
889 # Just in case CTRL+c
890 rm -f $DISTRO/gen
892 # Some packages may want to alter rootfs
893 genisohooks rootfs
894 cd $1
896 # Normalize file time
897 find $1 -newer $1 -exec touch -hr $1 {} \;
899 # Link duplicate files
900 deduplicate
902 # Use lzma if installed. Display rootfs size in realtime.
903 rm -f /tmp/rootfs 2>/dev/null
904 pack_rootfs . $DISTRO/$(basename $1).gz &
905 sleep 2
906 echo -en "\nFilesystem size:"
907 while [ ! -f /tmp/rootfs ]; do
908 sleep 1
909 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
910 done
911 echo -e "\n"
912 rm -f /tmp/rootfs
913 cd $DISTRO
914 mv $(basename $1).gz $ROOTCD/boot
915 }
918 distro_sizes() {
919 if [ -n "$start_time" ]; then
920 time=$(($(date +%s) - $start_time))
921 sec=$time
922 div=$(( ($time + 30) / 60))
923 [ "$div" -ne 0 ] && min="~ ${div}m"
924 _ 'Build time : %ss %s' "$sec" "$min"
925 fi
926 cat <<EOT
927 Build date : $(date +%Y%m%d)
928 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
929 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
930 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
931 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
932 EOT
933 footer "Image is ready: $ISO_NAME.iso"
934 }
937 # Print ISO and rootfs size.
939 distro_stats() {
940 title 'Distro statistics: %s' "$DISTRO"
941 distro_sizes
942 }
945 # Create an empty configuration file.
947 empty_config_file() {
948 cat >> tazlito.conf <<"EOF"
949 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
950 #
952 # Name of the ISO image to generate.
953 ISO_NAME=""
955 # ISO image volume name.
956 VOLUM_NAME="SliTaz"
958 # Name of the preparer.
959 PREPARED="$USER"
961 # Path to the packages repository and the packages.list.
962 PACKAGES_REPOSITORY=""
964 # Path to the distro tree to gen-distro from a list of packages.
965 DISTRO=""
967 # Path to the directory containing additional files
968 # to copy into the rootfs and rootcd of the LiveCD.
969 ADDFILES="$DISTRO/addfiles"
971 # Default answer for binary question (Y or N)
972 DEFAULT_ANSWER="ASK"
974 # Compression utility (lzma, gzip or none)
975 COMPRESSION="lzma"
976 EOF
977 }
980 # Extract rootfs.gz somewhere
982 extract_rootfs() {
983 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
984 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
985 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
986 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
987 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
988 }
991 # Extract flavor file to temp directory
993 extract_flavor() {
994 # Input: $1 - flavor name to extract;
995 # $2 = absent/empty: just extract 'outer layer'
996 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
997 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
998 # Output: temp dir path where flavor was extracted
999 local f="$1.flavor" from to infos="$1.desc"
1000 [ -f "$f" ] || die "File '$f' not found"
1001 local dir="$(mktemp -d)"
1002 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1004 if [ -n "$2" ]; then
1005 cd $dir
1007 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1009 for i in rootcd rootfs; do
1010 [ -f "$1.$i" ] || continue
1011 mkdir "$i"
1012 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1013 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1014 rm "$1.$i"
1015 done
1016 touch -t 197001010100.00 $1.*
1017 # Info to be stored inside ISO
1018 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
1019 rm $1.list*
1021 # Renames
1022 while read from to; do
1023 [ -f "$from" ] || continue
1024 mv "$from" "$to"
1025 done <<EOT
1026 $1.nonfree non-free.list
1027 $1.pkglist packages.list
1028 $1-distro.sh distro.sh
1029 $1.receipt receipt
1030 $1.mirrors mirrors
1031 $1.desc description
1032 EOT
1033 fi
1035 echo $dir
1039 # Pack flavor file from temp directory
1041 pack_flavor() {
1042 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1046 # Remove duplicate files
1048 files_match() {
1049 if [ -d "$1" ]; then
1050 return 1
1052 elif [ -L "$1" ] && [ -L "$2" ]; then
1053 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
1055 elif [ -f "$1" ] && [ -f "$2" ]; then
1056 cmp -s "$1" "$2" && return 0
1058 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
1059 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
1060 return 0
1062 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
1063 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1064 return 0
1066 fi 2> /dev/null
1067 return 1
1070 remove_with_path() {
1071 dir="$(dirname $1)"
1072 rm -f "$1"
1073 while rmdir "$dir" 2> /dev/null; do
1074 dir="$(dirname $dir)"
1075 done
1078 mergefs() {
1079 # Note, many packages have files with spaces in the name
1080 IFS=$'\n'
1082 local size1=$(du -hs "$1" | awk '{ print $1 }')
1083 local size2=$(du -hs "$2" | awk '{ print $1 }')
1084 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1086 # merge symlinks files and devices
1087 ( cd "$1"; find ) | \
1088 while read file; do
1089 files_match "$1/$file" "$2/$file" "$file" &&
1090 remove_with_path "$2/$file"
1091 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1092 done
1094 unset IFS
1095 status
1099 cleanup_merge() {
1100 rm -rf $TMP_DIR
1101 exit 1
1105 # Update isolinux config files for multiple rootfs
1107 update_bootconfig() {
1108 local files
1109 action 'Updating boot config files...'
1110 files="$(grep -l 'include common' $1/*.cfg)"
1111 for file in $files; do
1112 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1113 if (/label/) label=$0;
1114 else if (/kernel/) kernel=$0;
1115 else if (/append/) {
1116 i=index($0,"rootfs.gz");
1117 append=substr($0,i+9);
1119 else if (/include/) {
1120 for (i = 1; i <= n; i++) {
1121 print label i
1122 print kernel;
1123 initrd="initrd=/boot/rootfs" n ".gz"
1124 for (j = n - 1; j >= i; j--) {
1125 initrd=initrd ",/boot/rootfs" j ".gz";
1127 printf "\tappend %s%s\n",initrd,append;
1128 print "";
1130 print;
1132 else print;
1133 }' < $file > $file.$$
1134 mv -f $file.$$ $file
1135 done
1136 sel="$(echo $2 | awk '{
1137 for (i=1; i<=NF; i++)
1138 if (i % 2 == 0) printf " slitaz%d", i/2
1139 else printf " %s", $i
1140 }')"
1142 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1144 label slitaz
1145 kernel /boot/isolinux/ifmem.c32
1146 append$sel noram
1148 label noram
1149 config noram.cfg
1151 EOT
1153 # Update vesamenu
1154 if [ -s "$1/isolinux.cfg" ]; then
1155 files="$files $1/isolinux.cfg"
1156 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1157 BEGIN {
1158 kernel = " COM32 c32box.c32"
1161 if (/ROWS/) print "MENU ROWS " n+$3;
1162 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1163 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1164 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1165 else if (/VSHIFT/) {
1166 x = $3-n;
1167 if (x < 0) x = 0;
1168 print "MENU VSHIFT " x;
1170 else if (/rootfs.gz/) {
1171 linux = "";
1172 if (/bzImage/) linux = "linux /boot/bzImage ";
1173 i = index($0, "rootfs.gz");
1174 append = substr($0, i+9);
1175 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1176 printf "\tappend%s noram\n", sel;
1177 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1178 for (i = 1; i <= n; i++) {
1179 print "LABEL slitaz" i
1180 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1181 printf "%s\n", kernel;
1182 initrd = "initrd=/boot/rootfs" n ".gz"
1183 for (j = n - 1; j >= i; j--) {
1184 initrd = initrd ",/boot/rootfs" j ".gz";
1186 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1189 else if (/bzImage/) kernel = $0;
1190 else print;
1191 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1192 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1193 fi
1195 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1196 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1197 cat > $1/noram.cfg <<EOT
1198 implicit 0
1199 prompt 1
1200 timeout 80
1201 $(grep '^F[0-9]' $1/isolinux.cfg)
1203 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1204 say Not enough RAM to boot slitaz. Trying hacker mode...
1205 default hacker
1206 label hacker
1207 KERNEL /boot/bzImage
1208 append rw root=/dev/null vga=normal
1210 label reboot
1211 EOT
1213 if [ -s $1/c32box.c32 ]; then
1214 cat >> $1/noram.cfg <<EOT
1215 COM32 c32box.c32
1216 append reboot
1218 label poweroff
1219 COM32 c32box.c32
1220 append poweroff
1222 EOT
1223 else
1224 echo " com32 reboot.c32" >> $1/noram.cfg
1225 fi
1227 # Restore real label names
1228 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1229 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1230 while read pat; do
1231 sed -i "s/slitaz$pat/" $files
1232 done
1233 status
1237 # Uncompress rootfs or module to stdout
1239 uncompress() {
1240 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1241 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1245 # Install a missing package
1247 install_package() {
1248 if [ -z "$2" ]; then
1249 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1250 else
1251 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1252 fi
1253 case "$answer" in
1254 y)
1255 # We don't want package on host cache.
1256 action 'Getting and installing package: %s' "$1"
1257 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1258 status ;;
1259 *)
1260 return 1 ;;
1261 esac
1265 # Check iso for loram transformation
1267 check_iso_for_loram() {
1268 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1269 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1273 # Remove duplicated files in $1/efi/boot from $1/boot
1275 cleanup_efi_boot() {
1276 for i in $1/efi/boot/* ; do
1277 [ -f $i ] || continue
1278 cmp $i ${i/\/efi\//\/} 2> /dev/null || continue
1279 rm -f $i
1280 case "$i" in
1281 *vmlinuz*) sed -i '$d' $(dirname $i)/startup.nsh
1282 esac
1283 done
1287 # Build initial rootfs for loram ISO ram/cdrom/http
1289 build_initfs() {
1290 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1291 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1292 mirror3.slitaz.org mirror.slitaz.org"
1293 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1294 [ -z "$version" ] && die "Can't find the kernel version." \
1295 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1297 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1298 need_lib=false
1299 for i in bin dev run mnt proc tmp sys lib/modules; do
1300 mkdir -p $TMP_DIR/initfs/$i
1301 done
1302 ln -s bin $TMP_DIR/initfs/sbin
1303 ln -s . $TMP_DIR/initfs/usr
1304 for aufs in aufs overlayfs; do
1305 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1306 install_package linux-$aufs $version && break
1307 install_package $aufs $version && break
1308 done || return 1
1309 [ -s /init ] || install_package slitaz-boot-scripts
1310 cp /init $TMP_DIR/initfs/
1311 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1312 $TMP_DIR/initfs/lib/modules
1313 if [ "$1" == 'cdrom' ]; then
1314 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1315 else
1316 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1317 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1318 install_package linux-squashfs $version || return 1
1319 done
1320 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1321 $TMP_DIR/initfs/lib/modules
1322 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1323 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1324 fi
1325 if [ "$1" == 'http' ]; then
1326 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1327 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1328 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1329 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1330 cp -a /dev/fuse $TMP_DIR/initfs/dev
1331 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1332 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1333 else
1334 need_lib=true
1335 fi
1336 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1337 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1338 else
1339 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1340 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1341 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1342 cp -a /lib/librt* $TMP_DIR/initfs/lib
1343 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1344 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1345 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1346 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1347 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1348 need_lib=true
1349 fi
1350 cd $TMP_DIR/fs
1351 echo 'Getting slitaz-release & ethernet modules...'
1352 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1353 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1354 [ -s rootfs* ] || continue
1355 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1356 rm -f rootfs*
1357 done 2>&1 > /dev/null
1358 cd - > /dev/null
1359 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1360 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1361 -type f -name '*.ko*' | while read mod; do
1362 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1363 uncompress $mod > $f
1364 grep -q alias=pci: $f || rm -f $f
1365 done
1366 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1367 f=$(basename $i)..z
1368 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1369 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1370 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1371 for j in $deps; do
1372 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1373 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1374 done
1375 done
1376 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"
1377 _n 'List of URLs to insert: '
1378 read -t 30 urliso2
1379 urliso="$urliso2 $urliso"
1380 fi
1381 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1382 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1383 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1384 else
1385 cp /bin/busybox $TMP_DIR/initfs/bin
1386 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1387 cp /sbin/insmod $TMP_DIR/initfs/bin
1388 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1389 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1390 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1391 fi
1392 need_lib=true
1393 fi
1394 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1395 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1396 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1397 done
1398 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1399 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1400 $TMP_DIR/initfs/lib/modules 2>/dev/null
1401 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1402 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1403 cp -a $i $TMP_DIR/initfs/dev
1404 done
1405 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1406 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1407 cp -a $i $TMP_DIR/initfs/dev
1408 done 2>/dev/null
1409 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1410 cp -a $i $TMP_DIR/initfs/lib
1411 done
1412 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1413 #!/bin/sh
1415 getarg() {
1416 grep -q " \$1=" /proc/cmdline || return 1
1417 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1418 return 0
1421 copy_rootfs() {
1422 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1423 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1424 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1425 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1426 path=/mnt/
1427 return 0
1428 else
1429 rm -f /mnt/rootfs*
1430 return 1
1431 fi
1434 echo "Switching / to tmpfs..."
1435 mount -t proc proc /proc
1436 size="\$(grep rootfssize= < /proc/cmdline | \\
1437 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1438 [ -n "\$size" ] || size="-o size=90%"
1440 mount -t sysfs sysfs /sys
1441 for i in /lib/modules/*.ko ; do
1442 echo -en "Probe \$i \\r"
1443 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1444 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1445 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1446 insmod /lib/modules/\$k.ko 2> /dev/null
1447 done
1448 echo "Loading \$i"
1449 insmod \$i 2> /dev/null
1450 break
1451 done
1452 done
1453 umount /sys
1454 while read var default; do
1455 eval \$var=\$default
1456 getarg \$var \$var
1457 done <<EOT
1458 eth eth0
1459 dns 208.67.222.222,208.67.220.220
1460 netmask 255.255.255.0
1461 gw
1462 ip
1463 EOT
1464 grep -q \$eth /proc/net/dev || sh
1465 if [ -n "\$ip" ]; then
1466 ifconfig \$eth \$ip netmask \$netmask up
1467 route add default gateway \$gw
1468 for i in \$(echo \$dns | sed 's/,/ /g'); do
1469 echo "nameserver \$i" >> /etc/resolv.conf
1470 done
1471 else
1472 udhcpc -f -q -s /lib/udhcpc -i \$eth
1473 fi
1474 for i in $urliso ; do
1475 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1476 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"
1477 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1478 done
1479 getarg urliso URLISO
1480 DIR=fs
1481 if getarg loram DIR; then
1482 DEVICE=\${DIR%,*}
1483 DIR=/\${DIR#*,}
1484 fi
1485 mount -t tmpfs \$size tmpfs /mnt
1486 path2=/mnt/.httpfs/
1487 path=/mnt/.cdrom/
1488 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1489 while [ ! -d \$path/boot ]; do
1490 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1491 httpfs \$i \$path2 && echo \$i && break
1492 done
1493 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1494 done
1496 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1497 umount /proc
1498 branch=:/mnt/.cdrom/\$DIR
1499 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1500 branch=
1501 lp=1
1502 insmod /lib/modules/squashfs.ko 2> /dev/null
1503 for i in \${path}boot/rootfs?.* ; do
1504 fs=\${i#*root}
1505 branch=\$branch:/mnt/.\$fs
1506 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1507 losetup -o 124 /dev/loop\$lp \$i
1508 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1509 lp=\$((\$lp+1))
1510 done
1511 fi
1512 mkdir -p /mnt/.rw/mnt/.httpfs
1513 while read type opt; do
1514 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1515 done <<EOT
1516 aufs br=/mnt/.rw\$branch
1517 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1518 EOT
1519 rm -rf /lib/modules
1520 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1521 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1522 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1523 EOTEOT
1524 chmod +x $TMP_DIR/initfs/init
1525 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1526 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1527 rm -f $i
1528 done 2>/dev/null
1529 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1530 lzma e $TMP_DIR/initfs.gz -si
1531 lzma_set_size $TMP_DIR/initfs.gz
1532 rm -rf $TMP_DIR/initfs
1533 align_to_32bits $TMP_DIR/initfs.gz
1534 return 0
1538 # Move each initramfs to squashfs
1540 build_loram_rootfs() {
1541 rootfs_sizes=""
1542 for i in $TMP_DIR/iso/boot/rootfs*; do
1543 mkdir -p $TMP_DIR/fs
1544 cd $TMP_DIR/fs
1545 uncompress $i | cpio -idm
1546 deduplicate
1547 cd - > /dev/null
1548 rootfs=$TMP_DIR/$(basename $i)
1549 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1550 cd $TMP_DIR
1551 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1552 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1553 rm -f $rootfs
1554 mv $rootfs.cpio $rootfs
1555 cd - > /dev/null
1556 rm -rf $TMP_DIR/fs
1557 done
1561 # Move meta boot configuration files to basic configuration files
1562 # because meta loram flavor is useless when rootfs is not loaded in RAM
1564 unmeta_boot() {
1565 local root=${1:-$TMP_DIR/loramiso}
1566 if [ -f $root/boot/isolinux/noram.cfg ]; then
1567 # We keep enough information to do unloram...
1568 [ -s $root/boot/isolinux/common.cfg ] &&
1569 sed -i 's/label slitaz/label orgslitaz/' \
1570 $root/boot/isolinux/common.cfg
1571 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1572 shift
1573 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1574 $root/boot/isolinux/isolinux.cfg
1575 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1576 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1577 $root/boot/isolinux/*.cfg
1578 fi
1582 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1583 # These squashfs may be loaded in RAM at boot time.
1584 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1585 # Meta flavors are converted to normal flavors.
1587 build_loram_cdrom() {
1588 build_initfs cdrom || return 1
1589 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1590 cleanup_efi_boot $TMP_DIR/loramiso
1591 mkdir $TMP_DIR/loramiso/fs
1592 cd $TMP_DIR/loramiso/fs
1593 for i in $( ls ../boot/root* | sort -r ) ; do
1594 uncompress $i | cpio -idmu
1595 rm -f $i
1596 done
1597 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1598 cd - >/dev/null
1599 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1600 unmeta_boot
1601 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1602 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1603 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1604 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1605 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1606 create_iso $OUTPUT $TMP_DIR/loramiso
1610 # Create http bootstrap to load and remove loram_cdrom
1611 # Meta flavors are converted to normal flavors.
1613 build_loram_http() {
1614 build_initfs http || return 1
1615 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1616 cleanup_efi_boot $TMP_DIR/loramiso
1617 rm -f $TMP_DIR/loramiso/boot/rootfs*
1618 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1619 unmeta_boot
1620 create_iso $OUTPUT $TMP_DIR/loramiso
1624 # Update meta flavor selection sizes.
1625 # Reduce sizes with rootfs gains.
1627 update_metaiso_sizes() {
1628 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1629 do
1630 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1631 local sizes="$rootfs_sizes"
1632 local new
1633 set -- $append
1634 shift
1635 [ "$1" == "ifmem" ] && shift
1636 new=""
1637 while [ -n "$2" ]; do
1638 local s
1639 case "$1" in
1640 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1641 *M) s=$(( ${1%M} * 1024 ));;
1642 *) s=${1%K};;
1643 esac
1644 sizes=${sizes#* }
1645 for i in $sizes ; do
1646 s=$(( $s - $i ))
1647 done
1648 new="$new $s $2"
1649 shift 2
1650 done
1651 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1652 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1653 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1654 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1655 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1656 done
1660 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1661 # Meta flavor selection sizes are updated.
1663 build_loram_ram() {
1664 build_initfs ram || return 1
1665 build_loram_rootfs "$1"
1666 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1667 cleanup_efi_boot $TMP_DIR/loramiso
1668 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1669 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1670 update_metaiso_sizes
1671 create_iso $OUTPUT $TMP_DIR/loramiso
1675 # Remove files installed by packages
1677 find_flavor_rootfs() {
1678 for i in $1/etc/tazlito/*.extract; do
1679 [ -e $i ] || continue
1680 chroot $1 /bin/sh ${i#$1}
1681 done
1683 # Clean hardlinks and files patched by genisofs in /boot
1684 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1685 rm -f $1/boot/$i*
1686 done
1688 # Clean files generated in post_install
1689 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1690 $1/dev/core $1/dev/fd $1/dev/std*
1692 # Verify md5
1693 cat $1$INSTALLED/*/md5sum | \
1694 while read md5 file; do
1695 [ -e "$1$file" ] || continue
1696 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1697 rm -f "$1$file"
1698 done
1700 # Check configuration files
1701 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1702 [ -e $i ] || continue
1703 mkdir /tmp/volatile$$
1704 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1705 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1706 while read file ; do
1707 [ -e "$1/$file" ] || continue
1708 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1709 done
1710 rm -rf /tmp/volatile$$
1711 done
1713 # Remove other files blindly
1714 for i in $1$INSTALLED/*/files.list; do
1715 for file in $(cat "$i"); do
1716 [ "$1$file" -nt "$i" ] && continue
1717 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1718 [ -d "$1$file" ] || rm -f "$1$file"
1719 done
1720 done
1722 # Remove tazpkg files and tmp files
1723 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1724 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1725 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1726 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1727 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1729 # Cleanup directory tree
1730 cd $1
1731 find * -type d | sort -r | while read dir; do
1732 rmdir "$dir" 2>/dev/null
1733 done
1734 cd - > /dev/null
1738 # Get byte(s) from a binary file
1740 get() {
1741 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1745 # Get cpio flavor info from the ISO image
1747 flavordata() {
1748 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1749 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1753 # Restore undigest mirrors
1755 restore_mirrors() {
1756 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1757 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1759 action 'Restoring mirrors...'
1760 if [ -d "$undigest.bak" ]; then
1761 [ -d "$undigest" ] && rm -r "$undigest"
1762 mv "$undigest.bak" "$undigest"
1763 fi
1764 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1765 :; status
1769 # Setup undigest mirrors
1771 setup_mirrors() {
1772 # Setup mirrors in plain system or in chroot (with variable root=)
1773 local mirrorlist="$1" fresh repacked
1774 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1776 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1777 restore_mirrors
1779 _ 'Setting up mirrors for %s...' "$root/"
1780 # Backing up current undigest mirrors and priority
1781 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1782 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1783 rm -rf '/var/www/tazlito/'
1784 mkdir -p '/var/www/tazlito/'
1786 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1787 fresh='/home/slitaz/packages'
1788 if [ -d "$fresh" ]; then
1789 # Setup first undigest mirror
1790 mkdir -p "$undigest/fresh"
1791 echo "$fresh" > "$undigest/fresh/mirror"
1792 echo 'fresh' >> "$priority"
1793 # Rebuild mirror DB if needed
1794 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1795 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1796 tazpkg mkdb "$fresh" --forced --root=''
1797 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1798 fi
1800 # Repacked packages: high priority
1801 repacked="$PACKAGES_REPOSITORY"
1802 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1803 # According to Tazlito setup file (tazlito.conf):
1804 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1805 # or
1806 # WORK_DIR="/home/slitaz"
1807 # and
1808 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1809 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1811 # Setup second undigest mirror
1812 mkdir -p "$undigest/repacked"
1813 echo "$repacked" > "$undigest/repacked/mirror"
1814 echo 'repacked' >> "$priority"
1815 # Rebuild mirror DB if needed
1816 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1817 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1818 tazpkg mkdb "$repacked" --forced --root=''
1819 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1820 fi
1822 # All repositories listed in mirrors list: normal priority
1823 [ -e "$mirrorlist" ] && \
1824 while read mirror; do
1825 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1826 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1827 mkdir -p "$undigest/$mirrorid"
1828 echo "$mirror" > "$undigest/$mirrorid/mirror"
1829 echo "$mirrorid" >> "$priority"
1830 done < "$mirrorlist"
1832 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1834 # Show list of mirrors
1835 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1836 function show(num, name, url) {
1837 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1840 num++;
1841 "cat " db "/undigest/" $0 "/mirror" | getline url;
1842 show(num, $0, url);
1844 END {
1845 num++;
1846 "cat " db "/mirror" | getline url;
1847 show(num, "main", url);
1848 }' "$priority"
1850 tazpkg recharge --quiet >/dev/null
1854 # Get list of 'packages.info' lists using priority
1856 pi_lists() {
1857 local pi
1858 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1859 local priority="$root$LOCALSTATE/priority"
1860 local undigest="$root$LOCALSTATE/undigest"
1863 [ -s "$priority" ] && cat "$priority"
1864 echo 'main'
1865 [ -d "$undigest" ] && ls "$undigest"
1866 } | awk -vun="$undigest/" '
1868 if (arr[$0] != 1) {
1869 arr[$0] = 1;
1870 print un $0 "/packages.info";
1872 }' | sed 's|/undigest/main||' | \
1873 while read pi; do
1874 [ -e "$pi" ] && echo "$pi"
1875 done
1879 # Strip versions from packages list
1881 strip_versions() {
1882 if [ -n "$stripped" ]; then
1883 action 'Consider list %s already stripped' "$(basename "$1")"
1884 status
1885 return 0
1886 fi
1887 action 'Strip versions from list %s...' "$(basename "$1")"
1888 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1889 [ -f "$in_list" ] || die "List '$in_list' not found."
1891 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1892 awk '
1894 if (FILENAME ~ "packages.info") {
1895 # Collect package names
1896 FS = "\t"; pkg[$1] = 1;
1897 } else {
1898 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1899 while (NF > 1 && ! pkg[$0])
1900 NF --;
1901 printf "%s\n", $0;
1903 }' $(pi_lists) "$in_list" > "$tmp_list"
1905 cat "$tmp_list" > "$in_list"
1906 rm "$tmp_list"
1907 status
1911 # Display list of unknown packages (informative)
1913 display_unknown() {
1914 [ -s "$1" ] || return
1915 echo "Unknown packages:" >&2
1916 cat "$1" >&2
1917 rm "$1"
1921 # Display warnings about critical packages absent (informative)
1923 display_warn() {
1924 [ -s "$1" ] || return
1925 echo "Absent critical packages:" >&2
1926 cat "$1" >&2
1927 rm "$1"
1928 echo "Probably ISO image will be unusable."
1932 # Install packages to rootfs
1934 install_list_to_rootfs() {
1935 local list="$1" rootfs="$2" pkg i ii
1936 local undigest="$rootfs/var/lib/tazpkg/undigest"
1938 # initial tazpkg setup in empty rootfs
1939 tazpkg --root=$rootfs >/dev/null 2>&1
1940 # pass current 'mirror' to the rootfs
1941 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1942 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1943 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1944 # link rootfs packages cache to the regular packages cache
1945 rm -r "$rootfs/var/cache/tazpkg"
1946 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1948 setup_mirrors mirrors
1950 # Just in case if flavor doesn't contain "tazlito" package
1951 mkdir -p "$rootfs/etc/tazlito"
1953 newline
1955 # Choose detailed log with --detailed
1956 if [ -n "$detailed" ]; then
1957 while read pkg; do
1958 separator '-'
1959 echo $pkg
1960 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1961 done < $list
1962 separator '='
1963 else
1964 while read pkg; do
1965 action 'Installing package: %s' "$pkg"
1966 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1967 status
1968 done < $list
1969 fi
1970 newline
1972 restore_mirrors
1973 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1974 for i in fresh repacked; do
1975 ii="$undigest/$i"
1976 [ -d "$ii" ] && rm -rf "$ii"
1977 ii="$rootfs/var/lib/tazpkg/priority"
1978 if [ -f "$ii" ]; then
1979 sed -i "/$i/d" "$ii"
1980 [ -s "$ii" ] || rm "$ii"
1981 fi
1982 done
1983 [ -d "$undigest" ] && \
1984 for i in $(find "$undigest" -type f); do
1985 # Remove all undigest PKGDB files but 'mirror'
1986 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1987 done
1988 [ -d "$undigest" ] && \
1989 rmdir --ignore-fail-on-non-empty "$undigest"
1991 # Un-link packages cache
1992 rm "$rootfs/var/cache/tazpkg"
1994 # Clean /var/lib/tazpkg
1995 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2001 ####################
2002 # Tazlito commands #
2003 ####################
2005 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2006 case "$0" in
2007 *reduplicate)
2008 find ${@:-.} ! -type d -links +1 \
2009 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2010 exit 0 ;;
2011 *deduplicate)
2012 deduplicate "$@"
2013 exit 0 ;;
2014 esac
2017 case "$COMMAND" in
2018 stats)
2019 # Tazlito general statistics from the config file.
2021 title 'Tazlito statistics'
2022 optlist "\
2023 Config file : $CONFIG_FILE
2024 ISO name : $ISO_NAME.iso
2025 Volume name : $VOLUM_NAME
2026 Prepared : $PREPARED
2027 Packages repository : $PACKAGES_REPOSITORY
2028 Distro directory : $DISTRO
2029 Additional files : $ADDFILES
2030 " | sed '/: $/d'
2031 footer
2032 ;;
2035 list-addfiles)
2036 # Simple list of additional files in the rootfs
2037 newline
2038 if [ -d "$ADDFILES/rootfs" ]; then
2039 cd $ADDFILES
2040 find rootfs -type f
2041 else
2042 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2043 fi
2044 newline
2045 ;;
2048 gen-config)
2049 # Generate a new config file in the current dir or the specified
2050 # directory by $2.
2052 if [ -n "$2" ]; then
2053 mkdir -p "$2" && cd "$2"
2054 fi
2056 newline
2057 action 'Generating empty tazlito.conf...'
2058 empty_config_file
2059 status
2061 separator
2062 if [ -f 'tazlito.conf' ] ; then
2063 _ 'Configuration file is ready to edit.'
2064 _ 'File location: %s' "$(pwd)/tazlito.conf"
2065 newline
2066 fi
2067 ;;
2070 configure)
2071 # Configure a tazlito.conf config file. Start by getting
2072 # a empty config file and sed it.
2074 if [ -f 'tazlito.conf' ]; then
2075 rm tazlito.conf
2076 else
2077 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2078 'or in the same directory of the file you want to configure.'
2079 cd /etc
2080 fi
2082 empty_config_file
2084 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2086 # ISO name.
2087 echo -n "ISO name : " ; read answer
2088 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2089 # Volume name.
2090 echo -n "Volume name : " ; read answer
2091 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2092 # Packages repository.
2093 echo -n "Packages repository : " ; read answer
2094 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2095 # Distro path.
2096 echo -n "Distro path : " ; read answer
2097 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2098 footer "Config file is ready to use."
2099 echo 'You can now extract an ISO or generate a distro.'
2100 newline
2101 ;;
2104 gen-iso)
2105 # Simply generate a new iso.
2107 check_root
2108 verify_rootcd
2109 gen_livecd_isolinux
2110 distro_stats
2111 ;;
2114 gen-initiso)
2115 # Simply generate a new initramfs with a new iso.
2117 check_root
2118 verify_rootcd
2119 gen_initramfs "$ROOTFS"
2120 gen_livecd_isolinux
2121 distro_stats
2122 ;;
2125 extract-distro|extract-iso)
2126 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2128 check_root
2129 ISO_IMAGE="$2"
2130 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2131 'Example:\n tazlito image.iso /path/target'
2133 # Set the distro path by checking for $3 on cmdline.
2134 TARGET="${3:-$DISTRO}"
2136 # Exit if existing distro is found.
2137 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2138 'Please clean the distro tree or change directory path.'
2140 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2142 # Start to mount the ISO.
2143 action 'Mounting ISO image...'
2144 mkdir -p "$TMP_DIR"
2145 # Get ISO file size.
2146 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2147 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2148 sleep 2
2149 # Prepare target dir, copy the kernel and the rootfs.
2150 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2151 status
2153 action 'Copying the Linux kernel...'
2154 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2155 make_bzImage_hardlink "$TARGET/rootcd/boot"
2156 else
2157 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2158 fi
2159 status
2161 for i in $(ls $TMP_DIR); do
2162 [ "$i" == 'boot' ] && continue
2163 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2164 done
2166 for loader in isolinux syslinux extlinux grub; do
2167 [ -d "$TMP_DIR/boot/$loader" ] || continue
2168 action 'Copying %s files...' "$loader"
2169 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2170 status
2171 done
2173 action 'Copying the rootfs...'
2174 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2175 status
2177 # Extract initramfs.
2178 cd "$TARGET/rootfs"
2179 action 'Extracting the rootfs...'
2180 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2181 extract_rootfs "$i" "$TARGET/rootfs"
2182 done
2183 # unpack /usr
2184 for i in etc/tazlito/*.extract; do
2185 [ -f "$i" ] && . $i ../rootcd
2186 done
2187 # Umount and remove temp directory and cd to $TARGET to get stats.
2188 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2189 cd ..
2190 status
2192 newline
2193 separator
2194 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2195 echo "Distro tree : $(pwd)"
2196 echo "Rootfs size : $(du -sh rootfs)"
2197 echo "Rootcd size : $(du -sh rootcd)"
2198 footer
2199 ;;
2202 list-flavors)
2203 # Show available flavors.
2204 list='/etc/tazlito/flavors.list'
2205 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2206 title 'List of flavors'
2207 cat $list
2208 footer
2209 ;;
2212 show-flavor)
2213 # Show flavor descriptions.
2214 set -e
2215 flavor=${2%.flavor}
2216 flv_dir="$(extract_flavor "$flavor")"
2217 desc="$flv_dir/$flavor.desc"
2218 if [ -n "$brief" ]; then
2219 if [ -z "$noheader" ]; then
2220 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2221 separator
2222 fi
2223 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2224 "$(field ISO "$desc")" \
2225 "$(field Rootfs "$desc")" \
2226 "$(field Description "$desc")"
2227 else
2228 separator
2229 cat "$desc"
2230 fi
2231 cleanup
2232 ;;
2235 gen-liveflavor)
2236 # Generate a new flavor from the live system.
2237 FLAVOR=${2%.flavor}
2238 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2240 case "$FLAVOR" in
2241 -?|-h*|--help)
2242 cat <<EOT
2243 SliTaz Live Tool - Version: $VERSION
2245 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2247 $(boldify '<flavor-patch-file> format:')
2248 $(optlist "\
2249 code data
2250 + package to add
2251 - package to remove
2252 ! non-free package to add
2253 ? display message
2254 @ flavor description
2255 ")
2257 $(boldify 'Example:')
2258 $(optlist "\
2259 @ Developer tools for SliTaz maintainers
2260 + slitaz-toolchain
2261 + mercurial
2262 ")
2263 EOT
2264 exit 1
2265 ;;
2266 esac
2267 mv /etc/tazlito/distro-packages.list \
2268 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2269 rm -f distro-packages.list non-free.list 2>/dev/null
2270 tazpkg recharge
2272 DESC=""
2273 [ -n "$3" ] && \
2274 while read action pkg; do
2275 case "$action" in
2276 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2277 -) yes | tazpkg remove $pkg ;;
2278 !) echo $pkg >> non-free.list ;;
2279 @) DESC="$pkg" ;;
2280 \?) echo -en "$pkg"; read action ;;
2281 esac
2282 done < $3
2284 yes '' | tazlito gen-distro
2285 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2286 mv /etc/tazlito/distro-packages.list.$$ \
2287 /etc/tazlito/distro-packages.list 2>/dev/null
2288 ;;
2291 gen-flavor)
2292 # Generate a new flavor from the last ISO image generated
2293 FLAVOR=${2%.flavor}
2294 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2296 title 'Flavor generation'
2297 check_rootfs
2298 FILES="$FLAVOR.pkglist"
2300 action 'Creating file %s...' "$FLAVOR.flavor"
2301 for i in rootcd rootfs; do
2302 if [ -d "$ADDFILES/$i" ] ; then
2303 FILES="$FILES\n$FLAVOR.$i"
2304 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2305 fi
2306 done
2307 status
2309 answer=$(grep -s ^Description $FLAVOR.desc)
2310 answer=${answer#Description : }
2311 if [ -z "$answer" ]; then
2312 echo -n "Description: "
2313 read answer
2314 fi
2316 action 'Compressing flavor %s...' "$FLAVOR"
2317 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2318 echo "Description : $answer" >> $FLAVOR.desc
2319 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2320 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2321 for i in $(ls $ROOTFS$INSTALLED); do
2322 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2323 EXTRAVERSION=""
2324 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2325 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2326 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2327 echo "$i" >> $FLAVOR.nonfree
2328 else
2329 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2330 fi
2331 done
2332 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2333 for i in $LOCALSTATE/undigest/*/mirror ; do
2334 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2335 done
2336 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2337 touch -t 197001010100.00 $FLAVOR.*
2338 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2339 rm $(echo -e $FILES)
2340 status
2342 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2343 ;;
2346 upgrade-flavor)
2347 # Strip versions from pkglist and update estimated numbers in flavor.desc
2348 flavor="${2%.flavor}"
2349 set -e
2350 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2351 set +e
2353 flv_dir="$(extract_flavor "$flavor")"
2355 strip_versions "$flv_dir/$flavor.pkglist"
2357 action 'Updating %s...' "$flavor.desc"
2359 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2360 set -- $(module calc_sizes "$flv_dir" "$flavor")
2361 restore_mirrors >/dev/null
2363 sed -i -e '/Image is ready/d' \
2364 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2365 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2366 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2367 -e "s|\(Packages *:\).*$|\1 $4|" \
2368 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2369 "$flv_dir/$flavor.desc"
2371 pack_flavor "$flv_dir" "$flavor"
2372 status
2373 display_unknown "$flv_dir/err"
2374 display_warn "$flv_dir/warn"
2375 cleanup
2376 ;;
2379 extract-flavor)
2380 # Extract a flavor into $FLAVORS_REPOSITORY
2381 flavor="${2%.flavor}"
2382 set -e
2383 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2384 set +e
2386 action 'Extracting %s...' "$flavor.flavor"
2387 flv_dir="$(extract_flavor "$flavor" full)"
2388 storage="$FLAVORS_REPOSITORY/$flavor"
2390 rm -rf "$storage" 2>/dev/null
2391 mkdir -p "$storage"
2392 cp -a "$flv_dir"/* "$storage"
2393 rm "$storage/description"
2394 status
2396 strip_versions "$storage/packages.list"
2398 cleanup
2399 ;;
2402 pack-flavor)
2403 # Create a flavor from $FLAVORS_REPOSITORY.
2404 flavor=${2%.flavor}
2405 storage="$FLAVORS_REPOSITORY/$flavor"
2407 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2409 action 'Creating flavor %s...' "$flavor"
2410 tmp_dir="$(mktemp -d)"
2412 while read from to; do
2413 [ -s "$storage/$from" ] || continue
2414 cp -a "$storage/$from" "$tmp_dir/$to"
2415 done <<EOT
2416 mirrors $flavor.mirrors
2417 distro.sh $flavor-distro.sh
2418 receipt $flavor.receipt
2419 non-free.list $flavor.nonfree
2420 EOT
2422 # Build the package list.
2423 # It can include a list from another flavor with the keyword @include
2424 if [ -s "$storage/packages.list" ]; then
2425 include=$(grep '^@include' "$storage/packages.list")
2426 if [ -n "$include" ]; then
2427 include=${include#@include }
2428 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2429 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2430 else
2431 echo -e "\nERROR: Can't find include package list from $include\n"
2432 fi
2433 fi
2434 # Generate the final/initial package list
2435 [ -s "$storage/packages.list" ] && \
2436 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2437 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2438 fi
2440 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2441 # Process multi-rootfs flavor
2442 . "$storage/receipt"
2443 set -- $ROOTFS_SELECTION
2444 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2445 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2446 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2448 for i in rootcd rootfs; do
2449 mkdir "$tmp_dir/$i"
2450 # Copy extra files from the first flavor
2451 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2452 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2453 # Overload extra files by meta flavor
2454 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2455 [ -n "$(ls $tmp_dir/$i)" ] &&
2456 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2457 dogzip "$tmp_dir/$flavor.$i"
2458 rm -rf "$tmp_dir/$i"
2459 done
2460 else
2461 # Process plain flavor
2462 for i in rootcd rootfs; do
2463 [ -d "$storage/$i" ] || continue
2464 (cd "$storage/$i";
2465 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2466 done
2467 fi
2469 unset VERSION MAINTAINER ROOTFS_SELECTION
2470 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2471 ROOTFS_SIZE="$1 (estimated)"
2472 INITRAMFS_SIZE="$2 (estimated)"
2473 ISO_SIZE="$3 (estimated)"
2474 PKGNUM="$4"
2475 . "$storage/receipt"
2477 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2478 Flavor : $FLAVOR
2479 Description : $SHORT_DESC
2480 Version : $VERSION
2481 Maintainer : $MAINTAINER
2482 LiveCD RAM size : $FRUGAL_RAM
2483 Rootfs list : $ROOTFS_SELECTION
2484 Build date : $(date '+%Y%m%d at %T')
2485 Packages : $PKGNUM
2486 Rootfs size : $ROOTFS_SIZE
2487 Initramfs size : $INITRAMFS_SIZE
2488 ISO image size : $ISO_SIZE
2489 ================================================================================
2491 EOT
2493 rm -f $tmp_dir/packages.list
2494 pack_flavor "$tmp_dir" "$flavor"
2495 status
2496 display_unknown "$tmp_dir/err"
2497 display_warn "$flv_dir/warn"
2498 cleanup
2499 ;;
2502 get-flavor)
2503 # Get a flavor's files and prepare for gen-distro.
2504 flavor=${2%.flavor}
2505 title 'Preparing %s distro flavor' "$flavor"
2506 set -e
2507 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2508 set +e
2510 action 'Cleaning %s...' "$DISTRO"
2511 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2512 # Clean old files
2513 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2514 [ -f "$i" ] && rm "$i"
2515 done
2516 mkdir -p "$DISTRO"
2517 status
2519 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2521 action 'Extracting flavor %s...' "$flavor.flavor"
2522 flv_dir="$(extract_flavor "$flavor" info)"
2523 cp -a "$flv_dir"/* .
2524 mv packages.list distro-packages.list
2525 mv -f info /etc/tazlito
2526 status
2528 for i in rootcd rootfs; do
2529 if [ -d "$i" ]; then
2530 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2531 fi
2532 done
2534 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2535 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2537 action 'Updating %s...' 'tazlito.conf'
2538 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2539 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2540 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2541 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2542 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2543 status
2545 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2546 cleanup
2547 ;;
2550 iso2flavor)
2551 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2552 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2554 FLAVOR=${3%.flavor}
2555 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2556 mount -o loop,ro $2 $TMP_DIR/iso
2557 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2558 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2559 ! -s $TMP_DIR/flavor/*.desc ]; then
2560 _ 'META flavors are not supported.'
2561 umount -d $TMP_DIR/iso
2562 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2563 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2564 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2565 umount -d $TMP_DIR/iso
2566 else
2567 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2568 uncompress $i | \
2569 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2570 done
2571 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2572 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2573 '/etc/slitaz-release' '/boot/rootfs.gz'
2574 umount -d $TMP_DIR/iso
2575 else
2576 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2577 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2578 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2579 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2580 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2581 umount -d $TMP_DIR/iso
2582 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2583 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2584 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2585 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2586 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2587 < $TMP_DIR/rootfs$INSTALLED.md5
2588 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2589 if [ -s $TMP_DIR/flavor/*desc ]; then
2590 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2591 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2592 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2593 for i in rootfs rootcd ; do
2594 [ -s $TMP_DIR/flavor/*.list$i ] &&
2595 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2596 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2597 done
2598 else
2599 find_flavor_rootfs $TMP_DIR/rootfs
2600 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2601 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2602 for i in rootfs rootcd ; do
2603 [ "$(ls $TMP_DIR/$i)" ] &&
2604 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2605 done
2606 unset VERSION MAINTAINER
2607 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2608 if [ -n "$DESCRIPTION" ]; then
2609 _n 'Flavor version : '; read -t 30 VERSION
2610 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2611 fi
2613 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2614 Flavor : $FLAVOR
2615 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2616 Version : ${VERSION:-1.0}
2617 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2618 LiveCD RAM size : $RAM_SIZE
2619 Build date : $BUILD_DATE
2620 Packages : $PKGCNT
2621 Rootfs size : $ROOTFS_SIZE
2622 Initramfs size : $INITRAMFS_SIZE
2623 ISO image size : $ISO_SIZE
2624 ================================================================================
2626 EOT
2627 longline "Tazlito can't detect each file installed during \
2628 a package post_install. You should extract this flavor (tazlito extract-flavor \
2629 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2630 tree and remove files generated by post_installs.
2631 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2632 repack the flavor (tazlito pack-flavor $FLAVOR)"
2633 fi
2634 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2635 fi
2636 fi
2637 rm -rf $TMP_DIR
2638 ;;
2641 gen-distro)
2642 # Generate a live distro tree with a set of packages.
2644 check_root
2645 start_time=$(date +%s)
2647 # Tazlito options: --iso or --cdrom
2648 CDROM=''
2649 [ -n "$iso" ] && CDROM="-o loop $iso"
2650 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2652 # Check if a package list was specified on cmdline.
2653 if [ -f "$2" ]; then
2654 LIST_NAME="$2"
2655 else
2656 LIST_NAME='distro-packages.list'
2657 fi
2659 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2660 'Please clean the distro tree or change directory path.'
2661 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2662 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2664 # If list not given: build list with all installed packages
2665 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2666 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2667 fi
2669 # Exit if no list name.
2670 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2672 # Start generation.
2673 title 'Tazlito generating a distro'
2675 # Misc checks
2676 mkdir -p "$PACKAGES_REPOSITORY"
2677 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2678 newline
2680 # Mount CD-ROM to be able to repack boot-loader packages
2681 if [ ! -e /boot -a -n "$CDROM" ]; then
2682 mkdir $TMP_MNT
2683 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2684 ln -s "$TMP_MNT/boot" /
2685 if [ ! -d "$ADDFILES/rootcd" ] ; then
2686 mkdir -p "$ADDFILES/rootcd"
2687 for i in $(ls $TMP_MNT); do
2688 [ "$i" == 'boot' ] && continue
2689 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2690 done
2691 fi
2692 else
2693 rmdir "$TMP_MNT"
2694 fi
2695 fi
2697 # Rootfs stuff.
2698 echo 'Preparing the rootfs directory...'
2699 mkdir -p "$ROOTFS"
2700 export root="$ROOTFS"
2701 # pass current 'mirror' to the root
2702 mkdir -p $root/var/lib/tazpkg $root/etc
2703 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2704 cp -f /etc/slitaz-release $root/etc/slitaz-release
2705 strip_versions "$LIST_NAME"
2707 if [ "$REPACK" == 'y' ]; then
2708 # Determine full packages list with all dependencies
2709 tmp_dir="$(mktemp -d)"
2710 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2711 touch "$tmp_dir/full.pkglist"
2712 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2714 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2715 while read pkgname pkgver; do
2716 # Is package in full list?
2717 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2718 # Is package already repacked?
2719 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2720 _ 'Repacking %s...' "$pkgname-$pkgver"
2721 tazpkg repack "$pkgname" --quiet
2722 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2723 status
2724 done
2726 rm -r "$tmp_dir"
2727 fi
2729 if [ -f non-free.list ]; then
2730 # FIXME: working in the ROOTFS chroot?
2731 newline
2732 echo 'Preparing non-free packages...'
2733 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2734 for pkg in $(cat 'non-free.list'); do
2735 if [ ! -d "$INSTALLED/$pkg" ]; then
2736 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2737 tazpkg get-install get-$pkg
2738 fi
2739 get-$pkg "$ROOTFS"
2740 fi
2741 tazpkg repack $pkg
2742 pkg=$(ls $pkg*.tazpkg)
2743 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2744 mv $pkg $PACKAGES_REPOSITORY
2745 done
2746 fi
2747 cp $LIST_NAME $DISTRO/distro-packages.list
2748 newline
2750 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2752 cd $DISTRO
2753 cp distro-packages.list $ROOTFS/etc/tazlito
2754 # Copy all files from $ADDFILES/rootfs to the rootfs.
2755 if [ -d "$ADDFILES/rootfs" ] ; then
2756 action 'Copying addfiles content to the rootfs...'
2757 cp -a $ADDFILES/rootfs/* $ROOTFS
2758 status
2759 fi
2761 action 'Root filesystem is generated...'; status
2763 # Root CD part.
2764 action 'Preparing the rootcd directory...'
2765 mkdir -p $ROOTCD
2766 status
2768 # Move the boot dir with the Linux kernel from rootfs.
2769 # The efi & boot dirs go directly on the CD.
2770 if [ -d "$ROOTFS/efi" ] ; then
2771 action 'Moving the efi directory...'
2772 mv $ROOTFS/efi $ROOTCD
2773 status
2774 fi
2775 if [ -d "$ROOTFS/boot" ] ; then
2776 action 'Moving the boot directory...'
2777 mv $ROOTFS/boot $ROOTCD
2778 status
2779 fi
2780 cd $DISTRO
2781 # Copy all files from $ADDFILES/rootcd to the rootcd.
2782 if [ -d "$ADDFILES/rootcd" ] ; then
2783 action 'Copying addfiles content to the rootcd...'
2784 cp -a $ADDFILES/rootcd/* $ROOTCD
2785 status
2786 fi
2787 # Execute the distro script used to perform tasks in the rootfs
2788 # before compression. Give rootfs path in arg
2789 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2790 if [ -x "$DISTRO_SCRIPT" ]; then
2791 echo 'Executing distro script...'
2792 sh $DISTRO_SCRIPT $DISTRO
2793 fi
2795 # Execute the custom_rules() found in receipt.
2796 if [ -s "$TOP_DIR/receipt" ]; then
2797 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2798 echo -e "Executing: custom_rules()\n"
2799 . "$TOP_DIR/receipt"
2800 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2801 fi
2802 fi
2804 # Multi-rootfs
2805 if [ -s /etc/tazlito/rootfs.list ]; then
2807 FLAVOR_LIST="$(awk '{
2808 for (i = 2; i <= NF; i+=2)
2809 printf "%s ", $i;
2810 }' /etc/tazlito/rootfs.list)"
2812 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2813 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2814 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2816 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2817 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2818 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2819 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2821 n=0
2822 last=$ROOTFS
2823 while read flavor; do
2824 n=$(($n+1))
2825 mkdir ${ROOTFS}0$n
2826 export root="${ROOTFS}0$n"
2827 # initial tazpkg setup in empty rootfs
2828 tazpkg --root=$root >/dev/null 2>&1
2830 newline
2831 boldify "Building $flavor rootfs..."
2833 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2834 cp "$TOP_DIR/$flavor.flavor" .
2836 if [ ! -s "$flavor.flavor" ]; then
2837 # We may have it in $FLAVORS_REPOSITORY
2838 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2839 tazlito pack-flavor $flavor
2840 else
2841 download $flavor.flavor
2842 fi
2843 fi
2845 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2846 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2847 cp $flavor.pkglist $DISTRO/list-packages0$n
2848 status
2850 strip_versions "$DISTRO/list-packages0$n"
2852 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2854 action 'Updating the boot directory...'
2855 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2856 rm -rf ${ROOTFS}0$n/boot
2858 cd $DISTRO
2859 if [ -s $flavor.rootfs ]; then
2860 _n 'Adding %s rootfs extra files...' "$flavor"
2861 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2862 fi
2864 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2865 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2866 status
2868 rm -f $flavor.flavor install-list
2869 mergefs ${ROOTFS}0$n $last
2870 last=${ROOTFS}0$n
2871 done <<EOT
2872 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2873 EOT
2874 #'
2875 i=$(($n+1))
2876 while [ $n -gt 0 ]; do
2877 mv ${ROOTFS}0$n ${ROOTFS}$i
2878 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2879 gen_initramfs ${ROOTFS}$i
2880 n=$(($n-1))
2881 i=$(($i-1))
2882 export LZMA_HISTORY_BITS=26
2883 done
2884 mv $ROOTFS ${ROOTFS}$i
2885 gen_initramfs ${ROOTFS}$i
2886 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2887 ROOTFS=${ROOTFS}1
2888 else
2889 # Initramfs and ISO image stuff.
2890 gen_initramfs $ROOTFS
2891 fi
2892 gen_livecd_isolinux
2893 distro_stats
2894 cleanup
2895 ;;
2898 clean-distro)
2899 # Remove old distro tree.
2901 check_root
2902 title 'Cleaning: %s' "$DISTRO"
2903 if [ -d "$DISTRO" ] ; then
2904 if [ -d "$ROOTFS" ] ; then
2905 action 'Removing the rootfs...'
2906 rm -f $DISTRO/$INITRAMFS
2907 rm -rf $ROOTFS
2908 status
2909 fi
2910 if [ -d "$ROOTCD" ] ; then
2911 action 'Removing the rootcd...'
2912 rm -rf $ROOTCD
2913 status
2914 fi
2915 action 'Removing eventual ISO image...'
2916 rm -f $DISTRO/$ISO_NAME.iso
2917 rm -f $DISTRO/$ISO_NAME.md5
2918 status
2919 fi
2920 footer
2921 ;;
2924 check-distro)
2925 # Check for a few LiveCD needed files not installed by packages.
2927 # TODO: Remove this function.
2928 # First two files are maintained by tazpkg while it runs on rootfs,
2929 # while last one file should be maintained by tazlito itself.
2930 check_rootfs
2931 title 'Checking distro: %s' "$ROOTFS"
2932 # SliTaz release info.
2933 rel='/etc/slitaz-release'
2934 if [ ! -f "$ROOTFS$rel" ]; then
2935 _ 'Missing release info: %s' "$rel"
2936 else
2937 action 'Release : %s' "$(cat $ROOTFS$rel)"
2938 status
2939 fi
2940 # Tazpkg mirror.
2941 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2942 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2943 todomsg
2944 else
2945 action 'Mirror configuration exists...'
2946 status
2947 fi
2948 # Isolinux msg
2949 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2950 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2951 todomsg
2952 else
2953 action 'Isolinux message seems good...'
2954 status
2955 fi
2956 footer
2957 ;;
2960 writeiso)
2961 # Writefs to ISO image including /home unlike gen-distro we don't use
2962 # packages to generate a rootfs, we build a compressed rootfs with all
2963 # the current filesystem similar to 'tazusb writefs'.
2965 DISTRO='/home/slitaz/distro'
2966 ROOTCD="$DISTRO/rootcd"
2967 COMPRESSION="${2:-none}"
2968 ISO_NAME="${3:-slitaz}"
2969 check_root
2970 # Start info
2971 title 'Write filesystem to ISO'
2972 longline "The command writeiso will write the current filesystem into a \
2973 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2974 newline
2975 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2977 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2978 # Save some space
2979 rm -rf /var/cache/tazpkg/*
2980 rm -f /var/lib/tazpkg/*.bak
2981 rm -rf $DISTRO
2983 # Optionally remove sound card selection and screen resolution.
2984 if [ -z $LaunchedByTazpanel ]; then
2985 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2986 case $anser in
2987 y)
2988 action 'Removing current sound card and screen configurations...'
2989 rm -f /var/lib/sound-card-driver
2990 rm -f /var/lib/alsa/asound.state
2991 rm -f /etc/X11/xorg.conf ;;
2992 *)
2993 action 'Keeping current sound card and screen configurations...' ;;
2994 esac
2995 status
2996 newline
2998 # Optionally remove i18n settings
2999 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3000 case $anser in
3001 y)
3002 action 'Removing current locale/keymap settings...'
3003 newline > /etc/locale.conf
3004 newline > /etc/keymap.conf ;;
3005 *)
3006 action 'Keeping current locale/keymap settings...' ;;
3007 esac
3008 status
3009 fi
3011 # Clean-up files by default
3012 newline > /etc/udev/rules.d/70-persistent-net.rules
3013 newline > /etc/udev/rules.d/70-persistant-cd.rules
3015 # Create list of files including default user files since it is defined in /etc/passwd
3016 # and some new users might have been added.
3017 cd /
3018 echo 'init' > /tmp/list
3019 for dir in bin etc sbin var dev lib root usr home opt; do
3020 [ -d $dir ] && find $dir
3021 done >> /tmp/list
3023 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3024 [ -d $dir ] && echo $dir
3025 done >> /tmp/list
3027 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3029 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3030 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3031 #fi
3032 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3033 touch /var/log/wtmp
3035 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3036 sed -i "/var\/log\/$removelog/d" /tmp/list
3037 done
3039 # Generate initramfs with specified compression and display rootfs
3040 # size in realtime.
3041 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3043 write_initramfs &
3044 sleep 2
3045 cd - > /dev/null
3046 echo -en "\nFilesystem size:"
3047 while [ ! -f /tmp/rootfs ]; do
3048 sleep 1
3049 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3050 done
3051 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3052 echo -e "\n"
3053 rm -f /tmp/rootfs
3055 # Move freshly generated rootfs to the cdrom.
3056 mkdir -p $ROOTCD/boot
3057 mv -f /$INITRAMFS $ROOTCD/boot
3058 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3060 # Now we need the kernel and isolinux files.
3061 copy_from_cd() {
3062 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3063 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3064 unmeta_boot $ROOTCD
3065 umount /media/cdrom
3068 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3069 copy_from_cd;
3070 elif mount | grep /media/cdrom; then
3071 copy_from_cd;
3072 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3073 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3074 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3075 else
3076 touch /tmp/.write-iso-error
3077 longline "When SliTaz is running in RAM the kernel and bootloader \
3078 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3079 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3080 echo -en "----\nENTER to continue..."; read i
3081 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3082 copy_from_cd
3083 fi
3085 # Generate the iso image.
3086 touch /tmp/.write-iso
3087 newline
3088 cd $DISTRO
3089 create_iso $ISO_NAME.iso $ROOTCD
3090 action 'Creating the ISO md5sum...'
3091 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3092 status
3094 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3095 rm -f /tmp/.write-iso
3097 if [ -z $LaunchedByTazpanel ]; then
3098 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3099 case $anser in
3100 y)
3101 umount /dev/cdrom 2>/dev/null
3102 eject
3103 echo -n "Please insert a blank CD-ROM and press ENTER..."
3104 read i && sleep 2
3105 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3106 echo -en "----\nENTER to continue..."; read i ;;
3107 *)
3108 exit 0 ;;
3109 esac
3110 fi
3111 ;;
3114 burn-iso)
3115 # Guess CD-ROM device, ask user and burn the ISO.
3117 check_root
3118 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3119 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3120 # We can specify an alternative ISO from the cmdline.
3121 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3122 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3124 title 'Tazlito burn ISO'
3125 echo "CD-ROM device : /dev/$DRIVE_NAME"
3126 echo "Drive speed : $DRIVE_SPEED"
3127 echo "ISO image : $iso"
3128 footer
3130 case $(yesorno 'Burn ISO image?' 'n') in
3131 y)
3132 title 'Starting Wodim to burn the ISO...'
3133 sleep 2
3134 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3135 footer 'ISO image is burned to CD-ROM.'
3136 ;;
3137 *)
3138 die 'Exiting. No ISO burned.'
3139 ;;
3140 esac
3141 ;;
3144 merge)
3145 # Merge multiple rootfs into one iso.
3147 if [ -z "$2" ]; then
3148 cat <<EOT
3149 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3151 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3152 i.e: rootfsN is a subset of rootfsN-1
3153 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3154 The boot loader will select the rootfs according to the RAM size detected.
3156 Example:
3157 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3159 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3160 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3162 EOT
3163 exit 2
3164 fi
3166 shift # skip merge
3167 append="$1 slitaz1"
3168 shift # skip size1
3169 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3171 ISO=$1.merged
3173 # Extract filesystems
3174 action 'Mounting %s' "$1"
3175 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3176 status || cleanup_merge
3178 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3179 make_bzImage_hardlink $TMP_DIR/iso/boot
3180 umount -d $TMP_DIR/mnt
3181 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3182 _ '%s is already a merged iso. Aborting.' "$1"
3183 cleanup_merge
3184 fi
3185 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3186 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3187 if [ ! -f /boot/isolinux/ifmem.c32 -a
3188 ! -f /boot/isolinux/c32box.c32 ]; then
3189 cat <<EOT
3190 No file /boot/isolinux/ifmem.c32
3191 Please install syslinux package !
3192 EOT
3193 rm -rf $TMP_DIR
3194 exit 1
3195 fi
3196 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3197 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3198 fi
3200 action 'Extracting %s' 'iso/rootfs.gz'
3201 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3202 [ -d $TMP_DIR/rootfs1/etc ]
3203 status || cleanup_merge
3205 n=1
3206 while [ -n "$2" ]; do
3207 shift # skip rootfs N-1
3208 p=$n
3209 n=$(($n + 1))
3210 append="$append $1 slitaz$n"
3211 shift # skip size N
3212 mkdir -p $TMP_DIR/rootfs$n
3214 action 'Extracting %s' "$1"
3215 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3216 [ -d "$TMP_DIR/rootfs$n/etc" ]
3217 status || cleanup_merge
3219 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3220 action 'Creating %s' "rootfs$p.gz"
3221 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3222 status
3223 done
3224 action 'Creating %s' "rootfs$n.gz"
3225 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3226 status
3227 rm -f $TMP_DIR/iso/boot/rootfs.gz
3228 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3229 create_iso $ISO $TMP_DIR/iso
3230 rm -rf $TMP_DIR
3231 ;;
3234 repack)
3235 # Repack an iso with maximum lzma compression ratio.
3237 ISO=$2
3238 mkdir -p $TMP_DIR/mnt
3240 # Extract filesystems
3241 action 'Mounting %s' "$ISO"
3242 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3243 status || cleanup_merge
3245 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3246 umount -d $TMP_DIR/mnt
3248 for i in $TMP_DIR/iso/boot/rootfs* ; do
3249 action 'Repacking %s' "$(basename $i)"
3250 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3251 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3252 align_to_32bits $i
3253 status
3254 done
3256 create_iso $ISO $TMP_DIR/iso
3257 rm -rf $TMP_DIR
3258 ;;
3261 build-loram)
3262 # Build a Live CD for low RAM systems.
3264 ISO="$2"
3265 OUTPUT="$3"
3266 [ -z "$3" ] && \
3267 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3268 mkdir -p "$TMP_DIR/iso"
3269 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3270 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3271 if ! check_iso_for_loram ; then
3272 umount -d "$TMP_DIR/iso"
3273 die "$ISO is not a valid SliTaz live CD. Abort."
3274 fi
3275 case "$4" in
3276 cdrom) build_loram_cdrom ;;
3277 http) build_loram_http ;;
3278 *) build_loram_ram "$5" ;;
3279 esac
3280 umount $TMP_DIR/iso # no -d: needs /proc
3281 losetup -d $loopdev
3282 rm -rf $TMP_DIR
3283 ;;
3286 emu-iso)
3287 # Emulate an ISO image with Qemu.
3288 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3289 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3290 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3291 echo -e "\nStarting Qemu emulator:\n"
3292 echo -e "qemu $QEMU_OPTS $iso\n"
3293 qemu $QEMU_OPTS $iso
3294 ;;
3297 deduplicate)
3298 # Deduplicate files in a tree
3299 shift
3300 deduplicate "$@"
3301 ;;
3304 usage|*)
3305 # Print usage also for all unknown commands.
3306 usage
3307 ;;
3308 esac
3310 exit 0