tazlito view tazlito @ rev 505

fix cleanup_efi_boot
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed May 30 12:08:11 2018 +0200 (2018-05-30)
parents 6d164da69145
children 15343f90d12e
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2018 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
21 alias stat='busybox stat'
22 alias awk='busybox awk'
24 # Tazlito configuration variables to be shorter
25 # and to use words rather than numbers.
26 COMMAND="$1"
27 LIST_NAME="$2"
28 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
29 TMP_MNT="/media/tazlito-$$-$RANDOM"
30 TOP_DIR="$(pwd)"
31 INITRAMFS='rootfs.gz'
32 LOCALSTATE='/var/lib/tazpkg'
33 INSTALLED="$LOCALSTATE/installed"
34 CACHE_DIR='/var/cache/tazpkg'
35 MIRROR="$LOCALSTATE/mirror"
36 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
38 log='/var/log/tazlito.log'
39 if [ $(id -u) -eq 0 ]; then
40 newline > $log
41 fi
44 cleanup() {
45 if [ -d "$TMP_MNT" ]; then
46 umount $TMP_MNT
47 rmdir $TMP_MNT
48 rm -f /boot
49 fi
50 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
51 [ -d "$flv_dir" ] && rm -r "$flv_dir"
52 }
55 # Report error and finish work
57 die() {
58 emsg "<n>$(longline "$@")<n> " >&2
59 cleanup
60 exit 1
61 }
64 # Run Tazlito module
65 module() {
66 local mod="$1"; shift
67 /usr/libexec/tazlito/$mod $@
68 }
72 # Try to include config file, continue if command is gen-config or exit.
73 # The main config used by default is in /etc/tazlito.
74 # Specific distro config file can be put in a distro tree.
75 for i in /etc/tazlito "$TOP_DIR"; do
76 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
77 done
79 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
80 die 'Unable to find any configuration file.' \
81 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
83 . $CONFIG_FILE
85 # While Tazpkg is not used the default mirror URL file does not exist
86 # and user can't recharge the list of flavors.
87 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
89 # Set the rootfs and rootcd path with $DISTRO
90 # configuration variable.
91 ROOTFS="$DISTRO/rootfs"
92 ROOTCD="$DISTRO/rootcd"
97 #####################
98 # Tazlito functions #
99 #####################
102 # Print the usage.
104 usage () {
105 [ $(basename $0) == 'tazlito' ] && cat <<EOT
107 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
109 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
111 $(boldify "Commands:")
112 EOT
113 optlist "\
114 usage Print this short usage.
115 stats View Tazlito and distro configuration statistics.
116 list-addfiles Simple list of additional files in the rootfs.
117 gen-config Generate a new configuration file for a distro.
118 configure Configure the main config file or a specific tazlito.conf.
119 gen-iso Generate a new ISO from a distro tree.
120 gen-initiso Generate a new initramfs and ISO from the distro tree.
121 list-flavors List all flavors available on the mirror.
122 gen-flavor Generate a new Live CD description.
123 gen-liveflavor Generate a Live CD description from current system.
124 show-flavor Show Live CD description.
125 get-flavor Get a flavor's list of packages (--noup to skip update).
126 upgrade-flavor Update package list to the latest available versions.
127 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
128 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
129 iso2flavor Create a flavor file from a SliTaz ISO image.
130 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
131 gen-distro Generate a Live distro and ISO from a list of packages.
132 clean-distro Remove all files generated by gen-distro.
133 check-distro Help to check if distro is ready to release.
134 writeiso Use running system to generate a bootable ISO (with /home).
135 merge Merge multiple rootfs into one ISO.
136 deduplicate Deduplicate files in a tree.
137 repack Recompress rootfs into ISO with maximum ratio.
138 build-loram Generate a Live CD for low-RAM systems.
139 emu-iso Emulate an ISO image with QEMU.
140 burn-iso Burn ISO image to a CD-ROM using Wodim.
141 "
142 }
145 yesorno() {
146 local answer
147 echo -n "$1 (y=yes, n=no) [$2] " >&2
148 case "$DEFAULT_ANSWER" in
149 Y|y) answer="y";;
150 N|n) answer="n";;
151 *)
152 read -t 30 answer
153 [ -z "$answer" ] && answer="$2"
154 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
155 ;;
156 esac
157 echo "$answer"
158 }
161 field() {
162 grep "^$1" "$2" | \
163 case "$1" in
164 Desc*) sed 's|^.*: *||';;
165 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
166 esac
167 }
170 todomsg() {
171 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
172 }
175 # Download a file from this mirror
177 download_from() {
178 local i mirrors="$1"
179 shift
180 for i in $mirrors; do
181 case "$i" in
182 http://*|ftp://*|https://*)
183 wget -c $i$@ && break;;
184 *)
185 cp $i/$1 . && break;;
186 esac
187 done
188 }
191 # Download a file trying all mirrors
193 download() {
194 local i
195 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
196 download_from "$i" "$@" && break
197 done
198 }
201 # Execute hooks provided by some packages
203 genisohooks() {
204 local here="$(pwd)"
205 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
206 cd $ROOTFS
207 . $i $ROOTCD
208 done
209 cd "$here"
210 }
213 # Echo the package name if the tazpkg is already installed
215 installed_package_name() {
216 local tazpkg="$1" package VERSION EXTRAVERSION
218 # Try to find package name and version to be able
219 # to repack it from installation
220 # A dash (-) can exist in name *and* in version
221 package=${tazpkg%-*}
222 i=$package
223 while true; do
224 unset VERSION EXTRAVERSION
225 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
226 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
227 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
228 echo $i
229 break
230 fi
231 case "$i" in
232 *-*);;
233 *) break;;
234 esac
235 i=${i%-*}
236 done
237 }
240 # Check for the rootfs tree.
242 check_rootfs() {
243 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
244 }
247 # Check for the boot dir into the root CD tree.
249 verify_rootcd() {
250 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
251 }
253 set32() {
254 for i in $(seq 0 8 $((${4:-32}-8))); do
255 printf '\\\\x%02X' $((($2 >> $i) & 255))
256 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
257 }
259 set64() {
260 for i in $(seq 0 8 24 ; seq 24 -8 0); do
261 printf '\\\\x%02X' $((($2 >> $i) & 255))
262 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
263 }
266 first_block() {
267 busybox stat -m "$1" | sed q
268 }
272 # Force size and location in the 2nd eltorito boot file (/boot/isolinux/efi.img)
274 fix_efi_boot_img_size() {
275 local n=$3
276 [ $n -gt 65535 ] && n=65535
277 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
278 set32 $((0x1C+2048*$4)) $(($4*4)) $1
279 }
282 # Force the size for the /boot/isolinux/efi.img file
284 fix_efi_img_size() {
285 local e=$((0x809C))
286 for i in BOOT ISOLINUX EFI.IMG ; do
287 local sz=$(get $(($e+10)) "$2" 4)
288 e=$(($(get $(($e+2)) "$2" 4) * 2048))
289 while [ $sz -gt 0 ]; do
290 local len=$(get $e "$2")
291 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
292 2>/dev/null)" == "$i" ] && continue 2
293 [ $len -eq 0 ] && break
294 sz=$(($sz-$len))
295 e=$(($e+$len))
296 done
297 return # not found
298 done
299 set64 $(($e+10)) $1 "$2"
300 }
303 # create /boot/isolinux/efi.img to share EFI files with the iso image
305 fixup_uefi_part() {
306 [ -s $2/boot/isolinux/efi.img ] || return
307 local n=$(get 19 "$2/boot/isolinux/efi.img")
308 [ $n -eq 0 ] && n=$(get 32 "$2/boot/isolinux/efi.img" 4)
309 efiblock=$(first_block "$2/boot/isolinux/efi.img")
310 fix_efi_img_size $(($n*512)) $1
311 fix_efi_boot_img_size $1 $2 $n $efiblock
313 # Build file list tree
314 resv=$(get 14 "$2/boot/isolinux/efi.img")
315 if [ $(get 57 "$2/boot/isolinux/efi.img" 1) -ne 49 ]; then
316 skiphead=5
317 fatsz=$(get 36 "$2/boot/isolinux/efi.img" 4)
318 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
319 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
320 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
321 else
322 skiphead=4
323 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
324 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
325 fi 2> /dev/null
326 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead='$skiphead' }
327 {
328 if (skiphead!=0) {
329 if ($1=="*") skiphead--
330 next
331 }
332 if (skipdot!=0) {
333 if (skipdot==2) up[cur]=$13 $12
334 else cur=$13 $12
335 skipdot=0
336 next
337 }
338 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
339 if ($3=="2e") skipdot=2
340 else skipdot=1
341 next
342 }
343 if (gotname!=0) {
344 path=""
345 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
346 if (gotname==2) dir[$13 $12]=name
347 else print $1 " " $13 $12 " " path name
348 gotname=0
349 name=""
350 next
351 }
352 if (s!="") {
353 if (eos==0)
354 for (i=2;i<18;i+=2) {
355 if (i==12) i+=2
356 if ($i=="00") break
357 s=s substr($0,i+60,1)
358 }
359 name=s name
360 s=""
361 eos=0
362 next
363 }
364 if ($13=="0f") {
365 s=""
366 for (i=3;i<16;i+=2) {
367 if (i==13) i+=3
368 if ($i=="00") { eos=1; break }
369 s=s substr($0,i+60,1)
370 }
371 next
372 }
373 if ($13=="10") {
374 name=name "/"
375 gotname=2
376 next
377 }
378 if ($13=="20") {
379 gotname=1
380 next
381 }
382 }
383 ' | ( while read offset cluster file; do
384 cluster=$(($(first_block "$2/$file")-$basecluster))
385 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
386 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
387 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
388 done
390 # Update fat12 or fat16
391 get 57 "$2/boot/isolinux/efi.img"
392 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
393 od -An -t u1 -w1 -v
394 ) | awk '
395 {
396 if (state==0) {
397 if ($2=="") {
398 if ($1==12849) fat=12
399 else if ($1==13873) fat=16
400 else fat=32
401 state++
402 }
403 else {
404 for (i=1;i<$2;i++) c[$1+i]=$1+i
405 c[$1+$2]=268435455
406 }
407 next
408 }
409 if (state==1) {
410 prev=$1
411 state++
412 next
413 }
414 if (state==2) {
415 if (fat==12) {
416 n=($1%16)*256+prev
417 if (n!=0) c[pos+1]=n
418 pos++
419 prev=int($1/16)
420 state++
421 next
422 }
423 n=$1*256+prev
424 if (fat==32) {
425 prev=n
426 state=13
427 next
428 }
429 }
430 else if (state==3) {
431 n=$1*16+prev
432 }
433 else if (state==13) {
434 prev=$1*65536+prev
435 state++
436 next
437 }
438 else n=$1*16777216+prev
439 if (n!=0) c[pos+1]=n
440 pos++
441 state=1
442 }
443 END {
444 for (i=1;i<=pos;i+=2) {
445 if (c[i]=="") c[i]=0
446 if (c[i+1]=="") c[i+1]=0
447 if (fat==12) printf "0 %02X %1X%1X %02X |\n",c[i]%256,c[i+1]%16,(c[i]/256)%16,(c[i+1]/16)%256
448 else if (fat==16) printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,c[i+1]%256,(c[i+1]/256)%256
449 else {
450 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
451 printf "0 %02X %02X %02X %02X |\n",c[i+1]%256,(c[i+1]/256)%256,(c[i+1]/65536)%256,(c[i+1]/16777216)%256
452 }
453 }
454 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
455 conv=notrunc bs=512 > /dev/null 2>&1
456 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
457 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
459 # Cleanup cache
460 umount $2
461 mount -o loop,ro $1 $2
462 }
465 # allocate efi.img stub to share EFI files in the EFI boot partition
467 alloc_uefi_part() {
468 local basedir=$(dirname "$1")/..
469 local fclust=$({
470 [ -d $basedir/efi ] &&
471 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
472 while [ -s "$1" ]; do
473 local efifile
474 case "$1" in
475 *taz) efifile=bootia32.efi ;;
476 *taz64) efifile=bootx64.efi ;;
477 esac
478 if [ ! -s $basedir/efi/boot/$efifile ] &&
479 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
480 mkdir -p $basedir/efi/boot 2> /dev/null
481 ln "$1" "$basedir/efi/boot/$(basename $1).efi"
482 stat -c "%s %n" "$1"
483 for i in $basedir/boot/rootfs* ; do
484 ln "$i" $basedir/efi/boot/ &&
485 stat -c "%s %n" "$i"
486 done 2> /dev/null
487 efilinux="/EFI/BOOT/$(basename $1).efi"
488 sed 's|/|\\|g' >> $basedir/efi/boot/startup.nsh <<EOT
489 # start tazlito $efilinux
490 set -v num 0
491 for %i run (1 20)
492 if exist FS%num%:$efilinux then
493 FS%num%:
494 $efilinux rw root=0x100 autologin\
495 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
496 [ "$efifile" == "bootx64.efi" -a -s $basedir/efi/boot/${f}64 ] && \
497 f=${f}64; echo -n " initrd=/EFI/BOOT/$f";done)
498 endif
499 set -v num %i
500 endfor
501 # stop tazlito $efilinux
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 b=${i/\/efi\//\/}
1279 cmp $i ${b%.efi} || continue
1280 rm -f $i
1281 case "$i" in
1282 *vmlinuz*) sed -i '/# start tazlito /,/# stop tazlito /d' \
1283 $(dirname $i)/startup.nsh
1284 esac
1285 if [ ! -s $(dirname $i)/startup.nsh ]; then
1286 rm $(dirname $i)/startup.nsh
1287 rmdir $1/efi/boot && rmdir $1/efi
1288 fi
1289 done 2> /dev/null
1293 # Build initial rootfs for loram ISO ram/cdrom/http
1295 build_initfs() {
1296 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1297 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1298 mirror3.slitaz.org mirror.slitaz.org"
1299 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1300 [ -z "$version" ] && die "Can't find the kernel version." \
1301 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1303 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1304 need_lib=false
1305 for i in bin dev run mnt proc tmp sys lib/modules; do
1306 mkdir -p $TMP_DIR/initfs/$i
1307 done
1308 ln -s bin $TMP_DIR/initfs/sbin
1309 ln -s . $TMP_DIR/initfs/usr
1310 for aufs in aufs overlayfs; do
1311 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1312 install_package linux-$aufs $version && break
1313 install_package $aufs $version && break
1314 done || return 1
1315 [ -s /init ] || install_package slitaz-boot-scripts
1316 cp /init $TMP_DIR/initfs/
1317 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1318 $TMP_DIR/initfs/lib/modules
1319 if [ "$1" == 'cdrom' ]; then
1320 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1321 else
1322 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1323 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1324 install_package linux-squashfs $version || return 1
1325 done
1326 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1327 $TMP_DIR/initfs/lib/modules
1328 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1329 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1330 fi
1331 if [ "$1" == 'http' ]; then
1332 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1333 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1334 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1335 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1336 cp -a /dev/fuse $TMP_DIR/initfs/dev
1337 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1338 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1339 else
1340 need_lib=true
1341 fi
1342 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1343 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1344 else
1345 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1346 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1347 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1348 cp -a /lib/librt* $TMP_DIR/initfs/lib
1349 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1350 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1351 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1352 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1353 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1354 need_lib=true
1355 fi
1356 cd $TMP_DIR/fs
1357 echo 'Getting slitaz-release & ethernet modules...'
1358 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1359 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1360 [ -s rootfs* ] || continue
1361 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1362 rm -f rootfs*
1363 done 2>&1 > /dev/null
1364 cd - > /dev/null
1365 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1366 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1367 -type f -name '*.ko*' | while read mod; do
1368 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1369 uncompress $mod > $f
1370 grep -q alias=pci: $f || rm -f $f
1371 done
1372 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1373 f=$(basename $i)..z
1374 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1375 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1376 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1377 for j in $deps; do
1378 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1379 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1380 done
1381 done
1382 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"
1383 _n 'List of URLs to insert: '
1384 read -t 30 urliso2
1385 urliso="$urliso2 $urliso"
1386 fi
1387 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1388 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1389 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1390 else
1391 cp /bin/busybox $TMP_DIR/initfs/bin
1392 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1393 cp /sbin/insmod $TMP_DIR/initfs/bin
1394 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1395 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1396 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1397 fi
1398 need_lib=true
1399 fi
1400 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1401 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1402 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1403 done
1404 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1405 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1406 $TMP_DIR/initfs/lib/modules 2>/dev/null
1407 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1408 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1409 cp -a $i $TMP_DIR/initfs/dev
1410 done
1411 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1412 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1413 cp -a $i $TMP_DIR/initfs/dev
1414 done 2>/dev/null
1415 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1416 cp -a $i $TMP_DIR/initfs/lib
1417 done
1418 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1419 #!/bin/sh
1421 getarg() {
1422 grep -q " \$1=" /proc/cmdline || return 1
1423 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1424 return 0
1427 copy_rootfs() {
1428 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1429 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1430 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1431 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1432 path=/mnt/
1433 return 0
1434 else
1435 rm -f /mnt/rootfs*
1436 return 1
1437 fi
1440 echo "Switching / to tmpfs..."
1441 mount -t proc proc /proc
1442 size="\$(grep rootfssize= < /proc/cmdline | \\
1443 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1444 [ -n "\$size" ] || size="-o size=90%"
1446 mount -t sysfs sysfs /sys
1447 for i in /lib/modules/*.ko ; do
1448 echo -en "Probe \$i \\r"
1449 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1450 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1451 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1452 insmod /lib/modules/\$k.ko 2> /dev/null
1453 done
1454 echo "Loading \$i"
1455 insmod \$i 2> /dev/null
1456 break
1457 done
1458 done
1459 umount /sys
1460 while read var default; do
1461 eval \$var=\$default
1462 getarg \$var \$var
1463 done <<EOT
1464 eth eth0
1465 dns 208.67.222.222,208.67.220.220
1466 netmask 255.255.255.0
1467 gw
1468 ip
1469 EOT
1470 grep -q \$eth /proc/net/dev || sh
1471 if [ -n "\$ip" ]; then
1472 ifconfig \$eth \$ip netmask \$netmask up
1473 route add default gateway \$gw
1474 for i in \$(echo \$dns | sed 's/,/ /g'); do
1475 echo "nameserver \$i" >> /etc/resolv.conf
1476 done
1477 else
1478 udhcpc -f -q -s /lib/udhcpc -i \$eth
1479 fi
1480 for i in $urliso ; do
1481 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1482 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"
1483 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1484 done
1485 getarg urliso URLISO
1486 DIR=fs
1487 if getarg loram DIR; then
1488 DEVICE=\${DIR%,*}
1489 DIR=/\${DIR#*,}
1490 fi
1491 mount -t tmpfs \$size tmpfs /mnt
1492 path2=/mnt/.httpfs/
1493 path=/mnt/.cdrom/
1494 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1495 while [ ! -d \$path/boot ]; do
1496 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1497 httpfs \$i \$path2 && echo \$i && break
1498 done
1499 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1500 done
1502 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1503 umount /proc
1504 branch=:/mnt/.cdrom/\$DIR
1505 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1506 branch=
1507 lp=1
1508 insmod /lib/modules/squashfs.ko 2> /dev/null
1509 for i in \${path}boot/rootfs?.* ; do
1510 fs=\${i#*root}
1511 branch=\$branch:/mnt/.\$fs
1512 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1513 losetup -o 124 /dev/loop\$lp \$i
1514 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1515 lp=\$((\$lp+1))
1516 done
1517 fi
1518 mkdir -p /mnt/.rw/mnt/.httpfs
1519 while read type opt; do
1520 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1521 done <<EOT
1522 aufs br=/mnt/.rw\$branch
1523 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1524 EOT
1525 rm -rf /lib/modules
1526 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1527 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1528 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1529 EOTEOT
1530 chmod +x $TMP_DIR/initfs/init
1531 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1532 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1533 rm -f $i
1534 done 2>/dev/null
1535 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1536 lzma e $TMP_DIR/initfs.gz -si
1537 lzma_set_size $TMP_DIR/initfs.gz
1538 rm -rf $TMP_DIR/initfs
1539 align_to_32bits $TMP_DIR/initfs.gz
1540 return 0
1544 # Move each initramfs to squashfs
1546 build_loram_rootfs() {
1547 rootfs_sizes=""
1548 for i in $TMP_DIR/iso/boot/rootfs*; do
1549 mkdir -p $TMP_DIR/fs
1550 cd $TMP_DIR/fs
1551 uncompress $i | cpio -idm
1552 deduplicate
1553 cd - > /dev/null
1554 rootfs=$TMP_DIR/$(basename $i)
1555 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1556 cd $TMP_DIR
1557 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1558 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1559 rm -f $rootfs
1560 mv $rootfs.cpio $rootfs
1561 cd - > /dev/null
1562 rm -rf $TMP_DIR/fs
1563 done
1567 # Move meta boot configuration files to basic configuration files
1568 # because meta loram flavor is useless when rootfs is not loaded in RAM
1570 unmeta_boot() {
1571 local root=${1:-$TMP_DIR/loramiso}
1572 if [ -f $root/boot/isolinux/noram.cfg ]; then
1573 # We keep enough information to do unloram...
1574 [ -s $root/boot/isolinux/common.cfg ] &&
1575 sed -i 's/label slitaz/label orgslitaz/' \
1576 $root/boot/isolinux/common.cfg
1577 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1578 shift
1579 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1580 $root/boot/isolinux/isolinux.cfg
1581 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1582 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1583 $root/boot/isolinux/*.cfg
1584 fi
1588 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1589 # These squashfs may be loaded in RAM at boot time.
1590 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1591 # Meta flavors are converted to normal flavors.
1593 build_loram_cdrom() {
1594 build_initfs cdrom || return 1
1595 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1596 cleanup_efi_boot $TMP_DIR/loramiso
1597 mkdir $TMP_DIR/loramiso/fs
1598 cd $TMP_DIR/loramiso/fs
1599 for i in $( ls ../boot/root* | sort -r ) ; do
1600 uncompress $i | cpio -idmu
1601 rm -f $i
1602 done
1603 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1604 cd - >/dev/null
1605 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1606 unmeta_boot
1607 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1608 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1609 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1610 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1611 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1612 create_iso $OUTPUT $TMP_DIR/loramiso
1616 # Create http bootstrap to load and remove loram_cdrom
1617 # Meta flavors are converted to normal flavors.
1619 build_loram_http() {
1620 build_initfs http || return 1
1621 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1622 cleanup_efi_boot $TMP_DIR/loramiso
1623 rm -f $TMP_DIR/loramiso/boot/rootfs*
1624 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1625 unmeta_boot
1626 create_iso $OUTPUT $TMP_DIR/loramiso
1630 # Update meta flavor selection sizes.
1631 # Reduce sizes with rootfs gains.
1633 update_metaiso_sizes() {
1634 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1635 do
1636 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1637 local sizes="$rootfs_sizes"
1638 local new
1639 set -- $append
1640 shift
1641 [ "$1" == "ifmem" ] && shift
1642 new=""
1643 while [ -n "$2" ]; do
1644 local s
1645 case "$1" in
1646 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1647 *M) s=$(( ${1%M} * 1024 ));;
1648 *) s=${1%K};;
1649 esac
1650 sizes=${sizes#* }
1651 for i in $sizes ; do
1652 s=$(( $s - $i ))
1653 done
1654 new="$new $s $2"
1655 shift 2
1656 done
1657 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1658 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1659 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1660 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1661 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1662 done
1666 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1667 # Meta flavor selection sizes are updated.
1669 build_loram_ram() {
1670 build_initfs ram || return 1
1671 build_loram_rootfs "$1"
1672 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1673 cleanup_efi_boot $TMP_DIR/loramiso
1674 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1675 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1676 update_metaiso_sizes
1677 create_iso $OUTPUT $TMP_DIR/loramiso
1681 # Remove files installed by packages
1683 find_flavor_rootfs() {
1684 for i in $1/etc/tazlito/*.extract; do
1685 [ -e $i ] || continue
1686 chroot $1 /bin/sh ${i#$1}
1687 done
1689 # Clean hardlinks and files patched by genisofs in /boot
1690 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1691 rm -f $1/boot/$i*
1692 done
1694 # Clean files generated in post_install
1695 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1696 $1/dev/core $1/dev/fd $1/dev/std*
1698 # Verify md5
1699 cat $1$INSTALLED/*/md5sum | \
1700 while read md5 file; do
1701 [ -e "$1$file" ] || continue
1702 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1703 rm -f "$1$file"
1704 done
1706 # Check configuration files
1707 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1708 [ -e $i ] || continue
1709 mkdir /tmp/volatile$$
1710 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1711 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1712 while read file ; do
1713 [ -e "$1/$file" ] || continue
1714 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1715 done
1716 rm -rf /tmp/volatile$$
1717 done
1719 # Remove other files blindly
1720 for i in $1$INSTALLED/*/files.list; do
1721 for file in $(cat "$i"); do
1722 [ "$1$file" -nt "$i" ] && continue
1723 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1724 [ -d "$1$file" ] || rm -f "$1$file"
1725 done
1726 done
1728 # Remove tazpkg files and tmp files
1729 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1730 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1731 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1732 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1733 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1735 # Cleanup directory tree
1736 cd $1
1737 find * -type d | sort -r | while read dir; do
1738 rmdir "$dir" 2>/dev/null
1739 done
1740 cd - > /dev/null
1744 # Get byte(s) from a binary file
1746 get() {
1747 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1751 # Get cpio flavor info from the ISO image
1753 flavordata() {
1754 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1755 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1759 # Restore undigest mirrors
1761 restore_mirrors() {
1762 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1763 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1765 action 'Restoring mirrors...'
1766 if [ -d "$undigest.bak" ]; then
1767 [ -d "$undigest" ] && rm -r "$undigest"
1768 mv "$undigest.bak" "$undigest"
1769 fi
1770 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1771 :; status
1775 # Setup undigest mirrors
1777 setup_mirrors() {
1778 # Setup mirrors in plain system or in chroot (with variable root=)
1779 local mirrorlist="$1" fresh repacked
1780 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1782 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1783 restore_mirrors
1785 _ 'Setting up mirrors for %s...' "$root/"
1786 # Backing up current undigest mirrors and priority
1787 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1788 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1789 rm -rf '/var/www/tazlito/'
1790 mkdir -p '/var/www/tazlito/'
1792 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1793 fresh='/home/slitaz/packages'
1794 if [ -d "$fresh" ]; then
1795 # Setup first undigest mirror
1796 mkdir -p "$undigest/fresh"
1797 echo "$fresh" > "$undigest/fresh/mirror"
1798 echo 'fresh' >> "$priority"
1799 # Rebuild mirror DB if needed
1800 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1801 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1802 tazpkg mkdb "$fresh" --forced --root=''
1803 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1804 fi
1806 # Repacked packages: high priority
1807 repacked="$PACKAGES_REPOSITORY"
1808 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1809 # According to Tazlito setup file (tazlito.conf):
1810 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1811 # or
1812 # WORK_DIR="/home/slitaz"
1813 # and
1814 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1815 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1817 # Setup second undigest mirror
1818 mkdir -p "$undigest/repacked"
1819 echo "$repacked" > "$undigest/repacked/mirror"
1820 echo 'repacked' >> "$priority"
1821 # Rebuild mirror DB if needed
1822 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1823 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1824 tazpkg mkdb "$repacked" --forced --root=''
1825 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1826 fi
1828 # All repositories listed in mirrors list: normal priority
1829 [ -e "$mirrorlist" ] && \
1830 while read mirror; do
1831 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1832 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1833 mkdir -p "$undigest/$mirrorid"
1834 echo "$mirror" > "$undigest/$mirrorid/mirror"
1835 echo "$mirrorid" >> "$priority"
1836 done < "$mirrorlist"
1838 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1840 # Show list of mirrors
1841 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1842 function show(num, name, url) {
1843 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1846 num++;
1847 "cat " db "/undigest/" $0 "/mirror" | getline url;
1848 show(num, $0, url);
1850 END {
1851 num++;
1852 "cat " db "/mirror" | getline url;
1853 show(num, "main", url);
1854 }' "$priority"
1856 tazpkg recharge --quiet >/dev/null
1860 # Get list of 'packages.info' lists using priority
1862 pi_lists() {
1863 local pi
1864 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1865 local priority="$root$LOCALSTATE/priority"
1866 local undigest="$root$LOCALSTATE/undigest"
1869 [ -s "$priority" ] && cat "$priority"
1870 echo 'main'
1871 [ -d "$undigest" ] && ls "$undigest"
1872 } | awk -vun="$undigest/" '
1874 if (arr[$0] != 1) {
1875 arr[$0] = 1;
1876 print un $0 "/packages.info";
1878 }' | sed 's|/undigest/main||' | \
1879 while read pi; do
1880 [ -e "$pi" ] && echo "$pi"
1881 done
1885 # Strip versions from packages list
1887 strip_versions() {
1888 if [ -n "$stripped" ]; then
1889 action 'Consider list %s already stripped' "$(basename "$1")"
1890 status
1891 return 0
1892 fi
1893 action 'Strip versions from list %s...' "$(basename "$1")"
1894 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1895 [ -f "$in_list" ] || die "List '$in_list' not found."
1897 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1898 awk '
1900 if (FILENAME ~ "packages.info") {
1901 # Collect package names
1902 FS = "\t"; pkg[$1] = 1;
1903 } else {
1904 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1905 while (NF > 1 && ! pkg[$0])
1906 NF --;
1907 printf "%s\n", $0;
1909 }' $(pi_lists) "$in_list" > "$tmp_list"
1911 cat "$tmp_list" > "$in_list"
1912 rm "$tmp_list"
1913 status
1917 # Display list of unknown packages (informative)
1919 display_unknown() {
1920 [ -s "$1" ] || return
1921 echo "Unknown packages:" >&2
1922 cat "$1" >&2
1923 rm "$1"
1927 # Display warnings about critical packages absent (informative)
1929 display_warn() {
1930 [ -s "$1" ] || return
1931 echo "Absent critical packages:" >&2
1932 cat "$1" >&2
1933 rm "$1"
1934 echo "Probably ISO image will be unusable."
1938 # Install packages to rootfs
1940 install_list_to_rootfs() {
1941 local list="$1" rootfs="$2" pkg i ii
1942 local undigest="$rootfs/var/lib/tazpkg/undigest"
1944 # initial tazpkg setup in empty rootfs
1945 tazpkg --root=$rootfs >/dev/null 2>&1
1946 # pass current 'mirror' to the rootfs
1947 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1948 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1949 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1950 # link rootfs packages cache to the regular packages cache
1951 rm -r "$rootfs/var/cache/tazpkg"
1952 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1954 setup_mirrors mirrors
1956 # Just in case if flavor doesn't contain "tazlito" package
1957 mkdir -p "$rootfs/etc/tazlito"
1959 newline
1961 # Choose detailed log with --detailed
1962 if [ -n "$detailed" ]; then
1963 while read pkg; do
1964 separator '-'
1965 echo $pkg
1966 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1967 done < $list
1968 separator '='
1969 else
1970 while read pkg; do
1971 action 'Installing package: %s' "$pkg"
1972 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1973 status
1974 done < $list
1975 fi
1976 newline
1978 restore_mirrors
1979 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1980 for i in fresh repacked; do
1981 ii="$undigest/$i"
1982 [ -d "$ii" ] && rm -rf "$ii"
1983 ii="$rootfs/var/lib/tazpkg/priority"
1984 if [ -f "$ii" ]; then
1985 sed -i "/$i/d" "$ii"
1986 [ -s "$ii" ] || rm "$ii"
1987 fi
1988 done
1989 [ -d "$undigest" ] && \
1990 for i in $(find "$undigest" -type f); do
1991 # Remove all undigest PKGDB files but 'mirror'
1992 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1993 done
1994 [ -d "$undigest" ] && \
1995 rmdir --ignore-fail-on-non-empty "$undigest"
1997 # Un-link packages cache
1998 rm "$rootfs/var/cache/tazpkg"
2000 # Clean /var/lib/tazpkg
2001 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2007 ####################
2008 # Tazlito commands #
2009 ####################
2011 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2012 case "$0" in
2013 *reduplicate)
2014 find ${@:-.} ! -type d -links +1 \
2015 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2016 exit 0 ;;
2017 *deduplicate)
2018 deduplicate "$@"
2019 exit 0 ;;
2020 esac
2023 case "$COMMAND" in
2024 stats)
2025 # Tazlito general statistics from the config file.
2027 title 'Tazlito statistics'
2028 optlist "\
2029 Config file : $CONFIG_FILE
2030 ISO name : $ISO_NAME.iso
2031 Volume name : $VOLUM_NAME
2032 Prepared : $PREPARED
2033 Packages repository : $PACKAGES_REPOSITORY
2034 Distro directory : $DISTRO
2035 Additional files : $ADDFILES
2036 " | sed '/: $/d'
2037 footer
2038 ;;
2041 list-addfiles)
2042 # Simple list of additional files in the rootfs
2043 newline
2044 if [ -d "$ADDFILES/rootfs" ]; then
2045 cd $ADDFILES
2046 find rootfs -type f
2047 else
2048 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2049 fi
2050 newline
2051 ;;
2054 gen-config)
2055 # Generate a new config file in the current dir or the specified
2056 # directory by $2.
2058 if [ -n "$2" ]; then
2059 mkdir -p "$2" && cd "$2"
2060 fi
2062 newline
2063 action 'Generating empty tazlito.conf...'
2064 empty_config_file
2065 status
2067 separator
2068 if [ -f 'tazlito.conf' ] ; then
2069 _ 'Configuration file is ready to edit.'
2070 _ 'File location: %s' "$(pwd)/tazlito.conf"
2071 newline
2072 fi
2073 ;;
2076 configure)
2077 # Configure a tazlito.conf config file. Start by getting
2078 # a empty config file and sed it.
2080 if [ -f 'tazlito.conf' ]; then
2081 rm tazlito.conf
2082 else
2083 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2084 'or in the same directory of the file you want to configure.'
2085 cd /etc
2086 fi
2088 empty_config_file
2090 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2092 # ISO name.
2093 echo -n "ISO name : " ; read answer
2094 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2095 # Volume name.
2096 echo -n "Volume name : " ; read answer
2097 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2098 # Packages repository.
2099 echo -n "Packages repository : " ; read answer
2100 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2101 # Distro path.
2102 echo -n "Distro path : " ; read answer
2103 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2104 footer "Config file is ready to use."
2105 echo 'You can now extract an ISO or generate a distro.'
2106 newline
2107 ;;
2110 gen-iso)
2111 # Simply generate a new iso.
2113 check_root
2114 verify_rootcd
2115 gen_livecd_isolinux
2116 distro_stats
2117 ;;
2120 gen-initiso)
2121 # Simply generate a new initramfs with a new iso.
2123 check_root
2124 verify_rootcd
2125 gen_initramfs "$ROOTFS"
2126 gen_livecd_isolinux
2127 distro_stats
2128 ;;
2131 extract-distro|extract-iso)
2132 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2134 check_root
2135 ISO_IMAGE="$2"
2136 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2137 'Example:\n tazlito image.iso /path/target'
2139 # Set the distro path by checking for $3 on cmdline.
2140 TARGET="${3:-$DISTRO}"
2142 # Exit if existing distro is found.
2143 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2144 'Please clean the distro tree or change directory path.'
2146 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2148 # Start to mount the ISO.
2149 action 'Mounting ISO image...'
2150 mkdir -p "$TMP_DIR"
2151 # Get ISO file size.
2152 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2153 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2154 sleep 2
2155 # Prepare target dir, copy the kernel and the rootfs.
2156 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2157 status
2159 action 'Copying the Linux kernel...'
2160 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2161 make_bzImage_hardlink "$TARGET/rootcd/boot"
2162 else
2163 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2164 fi
2165 status
2167 for i in $(ls $TMP_DIR); do
2168 [ "$i" == 'boot' ] && continue
2169 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2170 done
2172 for loader in isolinux syslinux extlinux grub; do
2173 [ -d "$TMP_DIR/boot/$loader" ] || continue
2174 action 'Copying %s files...' "$loader"
2175 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2176 status
2177 done
2179 action 'Copying the rootfs...'
2180 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2181 status
2183 cleanup_efi_boot "$TARGET/rootcd"
2185 # Extract initramfs.
2186 cd "$TARGET/rootfs"
2187 action 'Extracting the rootfs...'
2188 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2189 extract_rootfs "$i" "$TARGET/rootfs"
2190 done
2191 # unpack /usr
2192 for i in etc/tazlito/*.extract; do
2193 [ -f "$i" ] && . $i ../rootcd
2194 done
2195 # Umount and remove temp directory and cd to $TARGET to get stats.
2196 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2197 cd ..
2198 status
2200 newline
2201 separator
2202 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2203 echo "Distro tree : $(pwd)"
2204 echo "Rootfs size : $(du -sh rootfs)"
2205 echo "Rootcd size : $(du -sh rootcd)"
2206 footer
2207 ;;
2210 list-flavors)
2211 # Show available flavors.
2212 list='/etc/tazlito/flavors.list'
2213 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2214 title 'List of flavors'
2215 cat $list
2216 footer
2217 ;;
2220 show-flavor)
2221 # Show flavor descriptions.
2222 set -e
2223 flavor=${2%.flavor}
2224 flv_dir="$(extract_flavor "$flavor")"
2225 desc="$flv_dir/$flavor.desc"
2226 if [ -n "$brief" ]; then
2227 if [ -z "$noheader" ]; then
2228 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2229 separator
2230 fi
2231 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2232 "$(field ISO "$desc")" \
2233 "$(field Rootfs "$desc")" \
2234 "$(field Description "$desc")"
2235 else
2236 separator
2237 cat "$desc"
2238 fi
2239 cleanup
2240 ;;
2243 gen-liveflavor)
2244 # Generate a new flavor from the live system.
2245 FLAVOR=${2%.flavor}
2246 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2248 case "$FLAVOR" in
2249 -?|-h*|--help)
2250 cat <<EOT
2251 SliTaz Live Tool - Version: $VERSION
2253 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2255 $(boldify '<flavor-patch-file> format:')
2256 $(optlist "\
2257 code data
2258 + package to add
2259 - package to remove
2260 ! non-free package to add
2261 ? display message
2262 @ flavor description
2263 ")
2265 $(boldify 'Example:')
2266 $(optlist "\
2267 @ Developer tools for SliTaz maintainers
2268 + slitaz-toolchain
2269 + mercurial
2270 ")
2271 EOT
2272 exit 1
2273 ;;
2274 esac
2275 mv /etc/tazlito/distro-packages.list \
2276 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2277 rm -f distro-packages.list non-free.list 2>/dev/null
2278 tazpkg recharge
2280 DESC=""
2281 [ -n "$3" ] && \
2282 while read action pkg; do
2283 case "$action" in
2284 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2285 -) yes | tazpkg remove $pkg ;;
2286 !) echo $pkg >> non-free.list ;;
2287 @) DESC="$pkg" ;;
2288 \?) echo -en "$pkg"; read action ;;
2289 esac
2290 done < $3
2292 yes '' | tazlito gen-distro
2293 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2294 mv /etc/tazlito/distro-packages.list.$$ \
2295 /etc/tazlito/distro-packages.list 2>/dev/null
2296 ;;
2299 gen-flavor)
2300 # Generate a new flavor from the last ISO image generated
2301 FLAVOR=${2%.flavor}
2302 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2304 title 'Flavor generation'
2305 check_rootfs
2306 FILES="$FLAVOR.pkglist"
2308 action 'Creating file %s...' "$FLAVOR.flavor"
2309 for i in rootcd rootfs; do
2310 if [ -d "$ADDFILES/$i" ] ; then
2311 FILES="$FILES\n$FLAVOR.$i"
2312 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2313 fi
2314 done
2315 status
2317 answer=$(grep -s ^Description $FLAVOR.desc)
2318 answer=${answer#Description : }
2319 if [ -z "$answer" ]; then
2320 echo -n "Description: "
2321 read answer
2322 fi
2324 action 'Compressing flavor %s...' "$FLAVOR"
2325 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2326 echo "Description : $answer" >> $FLAVOR.desc
2327 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2328 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2329 for i in $(ls $ROOTFS$INSTALLED); do
2330 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2331 EXTRAVERSION=""
2332 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2333 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2334 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2335 echo "$i" >> $FLAVOR.nonfree
2336 else
2337 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2338 fi
2339 done
2340 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2341 for i in $LOCALSTATE/undigest/*/mirror ; do
2342 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2343 done
2344 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2345 touch -t 197001010100.00 $FLAVOR.*
2346 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2347 rm $(echo -e $FILES)
2348 status
2350 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2351 ;;
2354 upgrade-flavor)
2355 # Strip versions from pkglist and update estimated numbers in flavor.desc
2356 flavor="${2%.flavor}"
2357 set -e
2358 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2359 set +e
2361 flv_dir="$(extract_flavor "$flavor")"
2363 strip_versions "$flv_dir/$flavor.pkglist"
2365 action 'Updating %s...' "$flavor.desc"
2367 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2368 set -- $(module calc_sizes "$flv_dir" "$flavor")
2369 restore_mirrors >/dev/null
2371 sed -i -e '/Image is ready/d' \
2372 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2373 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2374 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2375 -e "s|\(Packages *:\).*$|\1 $4|" \
2376 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2377 "$flv_dir/$flavor.desc"
2379 pack_flavor "$flv_dir" "$flavor"
2380 status
2381 display_unknown "$flv_dir/err"
2382 display_warn "$flv_dir/warn"
2383 cleanup
2384 ;;
2387 extract-flavor)
2388 # Extract a flavor into $FLAVORS_REPOSITORY
2389 flavor="${2%.flavor}"
2390 set -e
2391 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2392 set +e
2394 action 'Extracting %s...' "$flavor.flavor"
2395 flv_dir="$(extract_flavor "$flavor" full)"
2396 storage="$FLAVORS_REPOSITORY/$flavor"
2398 rm -rf "$storage" 2>/dev/null
2399 mkdir -p "$storage"
2400 cp -a "$flv_dir"/* "$storage"
2401 rm "$storage/description"
2402 status
2404 strip_versions "$storage/packages.list"
2406 cleanup
2407 ;;
2410 pack-flavor)
2411 # Create a flavor from $FLAVORS_REPOSITORY.
2412 flavor=${2%.flavor}
2413 storage="$FLAVORS_REPOSITORY/$flavor"
2415 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2417 action 'Creating flavor %s...' "$flavor"
2418 tmp_dir="$(mktemp -d)"
2420 while read from to; do
2421 [ -s "$storage/$from" ] || continue
2422 cp -a "$storage/$from" "$tmp_dir/$to"
2423 done <<EOT
2424 mirrors $flavor.mirrors
2425 distro.sh $flavor-distro.sh
2426 receipt $flavor.receipt
2427 non-free.list $flavor.nonfree
2428 EOT
2430 # Build the package list.
2431 # It can include a list from another flavor with the keyword @include
2432 if [ -s "$storage/packages.list" ]; then
2433 include=$(grep '^@include' "$storage/packages.list")
2434 if [ -n "$include" ]; then
2435 include=${include#@include }
2436 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2437 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2438 else
2439 echo -e "\nERROR: Can't find include package list from $include\n"
2440 fi
2441 fi
2442 # Generate the final/initial package list
2443 [ -s "$storage/packages.list" ] && \
2444 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2445 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2446 fi
2448 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2449 # Process multi-rootfs flavor
2450 . "$storage/receipt"
2451 set -- $ROOTFS_SELECTION
2452 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2453 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2454 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2456 for i in rootcd rootfs; do
2457 mkdir "$tmp_dir/$i"
2458 # Copy extra files from the first flavor
2459 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2460 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2461 # Overload extra files by meta flavor
2462 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2463 [ -n "$(ls $tmp_dir/$i)" ] &&
2464 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2465 dogzip "$tmp_dir/$flavor.$i"
2466 rm -rf "$tmp_dir/$i"
2467 done
2468 else
2469 # Process plain flavor
2470 for i in rootcd rootfs; do
2471 [ -d "$storage/$i" ] || continue
2472 (cd "$storage/$i";
2473 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2474 done
2475 fi
2477 unset VERSION MAINTAINER ROOTFS_SELECTION
2478 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2479 ROOTFS_SIZE="$1 (estimated)"
2480 INITRAMFS_SIZE="$2 (estimated)"
2481 ISO_SIZE="$3 (estimated)"
2482 PKGNUM="$4"
2483 . "$storage/receipt"
2485 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2486 Flavor : $FLAVOR
2487 Description : $SHORT_DESC
2488 Version : $VERSION
2489 Maintainer : $MAINTAINER
2490 LiveCD RAM size : $FRUGAL_RAM
2491 Rootfs list : $ROOTFS_SELECTION
2492 Build date : $(date '+%Y%m%d at %T')
2493 Packages : $PKGNUM
2494 Rootfs size : $ROOTFS_SIZE
2495 Initramfs size : $INITRAMFS_SIZE
2496 ISO image size : $ISO_SIZE
2497 ================================================================================
2499 EOT
2501 rm -f $tmp_dir/packages.list
2502 pack_flavor "$tmp_dir" "$flavor"
2503 status
2504 display_unknown "$tmp_dir/err"
2505 display_warn "$flv_dir/warn"
2506 cleanup
2507 ;;
2510 get-flavor)
2511 # Get a flavor's files and prepare for gen-distro.
2512 flavor=${2%.flavor}
2513 title 'Preparing %s distro flavor' "$flavor"
2514 set -e
2515 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2516 set +e
2518 action 'Cleaning %s...' "$DISTRO"
2519 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2520 # Clean old files
2521 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2522 [ -f "$i" ] && rm "$i"
2523 done
2524 mkdir -p "$DISTRO"
2525 status
2527 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2529 action 'Extracting flavor %s...' "$flavor.flavor"
2530 flv_dir="$(extract_flavor "$flavor" info)"
2531 cp -a "$flv_dir"/* .
2532 mv packages.list distro-packages.list
2533 mv -f info /etc/tazlito
2534 status
2536 for i in rootcd rootfs; do
2537 if [ -d "$i" ]; then
2538 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2539 fi
2540 done
2542 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2543 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2545 action 'Updating %s...' 'tazlito.conf'
2546 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2547 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2548 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2549 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2550 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2551 status
2553 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2554 cleanup
2555 ;;
2558 iso2flavor)
2559 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2560 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2562 FLAVOR=${3%.flavor}
2563 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2564 mount -o loop,ro $2 $TMP_DIR/iso
2565 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2566 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2567 ! -s $TMP_DIR/flavor/*.desc ]; then
2568 _ 'META flavors are not supported.'
2569 umount -d $TMP_DIR/iso
2570 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2571 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2572 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2573 umount -d $TMP_DIR/iso
2574 else
2575 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2576 uncompress $i | \
2577 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2578 done
2579 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2580 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2581 '/etc/slitaz-release' '/boot/rootfs.gz'
2582 umount -d $TMP_DIR/iso
2583 else
2584 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2585 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2586 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2587 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2588 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2589 umount -d $TMP_DIR/iso
2590 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2591 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2592 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2593 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2594 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2595 < $TMP_DIR/rootfs$INSTALLED.md5
2596 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2597 if [ -s $TMP_DIR/flavor/*desc ]; then
2598 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2599 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2600 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2601 for i in rootfs rootcd ; do
2602 [ -s $TMP_DIR/flavor/*.list$i ] &&
2603 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2604 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2605 done
2606 else
2607 find_flavor_rootfs $TMP_DIR/rootfs
2608 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2609 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2610 for i in rootfs rootcd ; do
2611 [ "$(ls $TMP_DIR/$i)" ] &&
2612 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2613 done
2614 unset VERSION MAINTAINER
2615 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2616 if [ -n "$DESCRIPTION" ]; then
2617 _n 'Flavor version : '; read -t 30 VERSION
2618 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2619 fi
2621 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2622 Flavor : $FLAVOR
2623 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2624 Version : ${VERSION:-1.0}
2625 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2626 LiveCD RAM size : $RAM_SIZE
2627 Build date : $BUILD_DATE
2628 Packages : $PKGCNT
2629 Rootfs size : $ROOTFS_SIZE
2630 Initramfs size : $INITRAMFS_SIZE
2631 ISO image size : $ISO_SIZE
2632 ================================================================================
2634 EOT
2635 longline "Tazlito can't detect each file installed during \
2636 a package post_install. You should extract this flavor (tazlito extract-flavor \
2637 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2638 tree and remove files generated by post_installs.
2639 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2640 repack the flavor (tazlito pack-flavor $FLAVOR)"
2641 fi
2642 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2643 fi
2644 fi
2645 rm -rf $TMP_DIR
2646 ;;
2649 gen-distro)
2650 # Generate a live distro tree with a set of packages.
2652 check_root
2653 start_time=$(date +%s)
2655 # Tazlito options: --iso or --cdrom
2656 CDROM=''
2657 [ -n "$iso" ] && CDROM="-o loop $iso"
2658 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2660 # Check if a package list was specified on cmdline.
2661 if [ -f "$2" ]; then
2662 LIST_NAME="$2"
2663 else
2664 LIST_NAME='distro-packages.list'
2665 fi
2667 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2668 'Please clean the distro tree or change directory path.'
2669 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2670 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2672 # If list not given: build list with all installed packages
2673 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2674 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2675 fi
2677 # Exit if no list name.
2678 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2680 # Start generation.
2681 title 'Tazlito generating a distro'
2683 # Misc checks
2684 mkdir -p "$PACKAGES_REPOSITORY"
2685 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2686 newline
2688 # Mount CD-ROM to be able to repack boot-loader packages
2689 if [ ! -e /boot -a -n "$CDROM" ]; then
2690 mkdir $TMP_MNT
2691 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2692 ln -s "$TMP_MNT/boot" /
2693 if [ ! -d "$ADDFILES/rootcd" ] ; then
2694 mkdir -p "$ADDFILES/rootcd"
2695 for i in $(ls $TMP_MNT); do
2696 [ "$i" == 'boot' ] && continue
2697 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2698 done
2699 fi
2700 else
2701 rmdir "$TMP_MNT"
2702 fi
2703 fi
2705 # Rootfs stuff.
2706 echo 'Preparing the rootfs directory...'
2707 mkdir -p "$ROOTFS"
2708 export root="$ROOTFS"
2709 # pass current 'mirror' to the root
2710 mkdir -p $root/var/lib/tazpkg $root/etc
2711 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2712 cp -f /etc/slitaz-release $root/etc/slitaz-release
2713 strip_versions "$LIST_NAME"
2715 if [ "$REPACK" == 'y' ]; then
2716 # Determine full packages list with all dependencies
2717 tmp_dir="$(mktemp -d)"
2718 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2719 touch "$tmp_dir/full.pkglist"
2720 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2722 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2723 while read pkgname pkgver; do
2724 # Is package in full list?
2725 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2726 # Is package already repacked?
2727 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2728 _ 'Repacking %s...' "$pkgname-$pkgver"
2729 tazpkg repack "$pkgname" --quiet
2730 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2731 status
2732 done
2734 rm -r "$tmp_dir"
2735 fi
2737 if [ -f non-free.list ]; then
2738 # FIXME: working in the ROOTFS chroot?
2739 newline
2740 echo 'Preparing non-free packages...'
2741 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2742 for pkg in $(cat 'non-free.list'); do
2743 if [ ! -d "$INSTALLED/$pkg" ]; then
2744 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2745 tazpkg get-install get-$pkg
2746 fi
2747 get-$pkg "$ROOTFS"
2748 fi
2749 tazpkg repack $pkg
2750 pkg=$(ls $pkg*.tazpkg)
2751 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2752 mv $pkg $PACKAGES_REPOSITORY
2753 done
2754 fi
2755 cp $LIST_NAME $DISTRO/distro-packages.list
2756 newline
2758 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2760 cd $DISTRO
2761 cp distro-packages.list $ROOTFS/etc/tazlito
2762 # Copy all files from $ADDFILES/rootfs to the rootfs.
2763 if [ -d "$ADDFILES/rootfs" ] ; then
2764 action 'Copying addfiles content to the rootfs...'
2765 cp -a $ADDFILES/rootfs/* $ROOTFS
2766 status
2767 fi
2769 action 'Root filesystem is generated...'; status
2771 # Root CD part.
2772 action 'Preparing the rootcd directory...'
2773 mkdir -p $ROOTCD
2774 status
2776 # Move the boot dir with the Linux kernel from rootfs.
2777 # The efi & boot dirs go directly on the CD.
2778 if [ -d "$ROOTFS/efi" ] ; then
2779 action 'Moving the efi directory...'
2780 mv $ROOTFS/efi $ROOTCD
2781 status
2782 fi
2783 if [ -d "$ROOTFS/boot" ] ; then
2784 action 'Moving the boot directory...'
2785 mv $ROOTFS/boot $ROOTCD
2786 status
2787 fi
2788 cd $DISTRO
2789 # Copy all files from $ADDFILES/rootcd to the rootcd.
2790 if [ -d "$ADDFILES/rootcd" ] ; then
2791 action 'Copying addfiles content to the rootcd...'
2792 cp -a $ADDFILES/rootcd/* $ROOTCD
2793 status
2794 fi
2795 # Execute the distro script used to perform tasks in the rootfs
2796 # before compression. Give rootfs path in arg
2797 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2798 if [ -x "$DISTRO_SCRIPT" ]; then
2799 echo 'Executing distro script...'
2800 sh $DISTRO_SCRIPT $DISTRO
2801 fi
2803 # Execute the custom_rules() found in receipt.
2804 if [ -s "$TOP_DIR/receipt" ]; then
2805 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2806 echo -e "Executing: custom_rules()\n"
2807 . "$TOP_DIR/receipt"
2808 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2809 fi
2810 fi
2812 # Multi-rootfs
2813 if [ -s /etc/tazlito/rootfs.list ]; then
2815 FLAVOR_LIST="$(awk '{
2816 for (i = 2; i <= NF; i+=2)
2817 printf "%s ", $i;
2818 }' /etc/tazlito/rootfs.list)"
2820 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2821 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2822 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2824 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2825 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2826 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2827 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2829 n=0
2830 last=$ROOTFS
2831 while read flavor; do
2832 n=$(($n+1))
2833 mkdir ${ROOTFS}0$n
2834 export root="${ROOTFS}0$n"
2835 # initial tazpkg setup in empty rootfs
2836 tazpkg --root=$root >/dev/null 2>&1
2838 newline
2839 boldify "Building $flavor rootfs..."
2841 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2842 cp "$TOP_DIR/$flavor.flavor" .
2844 if [ ! -s "$flavor.flavor" ]; then
2845 # We may have it in $FLAVORS_REPOSITORY
2846 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2847 tazlito pack-flavor $flavor
2848 else
2849 download $flavor.flavor
2850 fi
2851 fi
2853 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2854 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2855 cp $flavor.pkglist $DISTRO/list-packages0$n
2856 status
2858 strip_versions "$DISTRO/list-packages0$n"
2860 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2862 action 'Updating the boot directory...'
2863 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2864 rm -rf ${ROOTFS}0$n/boot
2866 cd $DISTRO
2867 if [ -s $flavor.rootfs ]; then
2868 _n 'Adding %s rootfs extra files...' "$flavor"
2869 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2870 fi
2872 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2873 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2874 status
2876 rm -f $flavor.flavor install-list
2877 mergefs ${ROOTFS}0$n $last
2878 last=${ROOTFS}0$n
2879 done <<EOT
2880 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2881 EOT
2882 #'
2883 i=$(($n+1))
2884 while [ $n -gt 0 ]; do
2885 mv ${ROOTFS}0$n ${ROOTFS}$i
2886 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2887 gen_initramfs ${ROOTFS}$i
2888 n=$(($n-1))
2889 i=$(($i-1))
2890 export LZMA_HISTORY_BITS=26
2891 done
2892 mv $ROOTFS ${ROOTFS}$i
2893 gen_initramfs ${ROOTFS}$i
2894 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2895 ROOTFS=${ROOTFS}1
2896 else
2897 # Initramfs and ISO image stuff.
2898 gen_initramfs $ROOTFS
2899 fi
2900 gen_livecd_isolinux
2901 distro_stats
2902 cleanup
2903 ;;
2906 clean-distro)
2907 # Remove old distro tree.
2909 check_root
2910 title 'Cleaning: %s' "$DISTRO"
2911 if [ -d "$DISTRO" ] ; then
2912 if [ -d "$ROOTFS" ] ; then
2913 action 'Removing the rootfs...'
2914 rm -f $DISTRO/$INITRAMFS
2915 rm -rf $ROOTFS
2916 status
2917 fi
2918 if [ -d "$ROOTCD" ] ; then
2919 action 'Removing the rootcd...'
2920 rm -rf $ROOTCD
2921 status
2922 fi
2923 action 'Removing eventual ISO image...'
2924 rm -f $DISTRO/$ISO_NAME.iso
2925 rm -f $DISTRO/$ISO_NAME.md5
2926 status
2927 fi
2928 footer
2929 ;;
2932 check-distro)
2933 # Check for a few LiveCD needed files not installed by packages.
2935 # TODO: Remove this function.
2936 # First two files are maintained by tazpkg while it runs on rootfs,
2937 # while last one file should be maintained by tazlito itself.
2938 check_rootfs
2939 title 'Checking distro: %s' "$ROOTFS"
2940 # SliTaz release info.
2941 rel='/etc/slitaz-release'
2942 if [ ! -f "$ROOTFS$rel" ]; then
2943 _ 'Missing release info: %s' "$rel"
2944 else
2945 action 'Release : %s' "$(cat $ROOTFS$rel)"
2946 status
2947 fi
2948 # Tazpkg mirror.
2949 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2950 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2951 todomsg
2952 else
2953 action 'Mirror configuration exists...'
2954 status
2955 fi
2956 # Isolinux msg
2957 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2958 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2959 todomsg
2960 else
2961 action 'Isolinux message seems good...'
2962 status
2963 fi
2964 footer
2965 ;;
2968 writeiso)
2969 # Writefs to ISO image including /home unlike gen-distro we don't use
2970 # packages to generate a rootfs, we build a compressed rootfs with all
2971 # the current filesystem similar to 'tazusb writefs'.
2973 DISTRO='/home/slitaz/distro'
2974 ROOTCD="$DISTRO/rootcd"
2975 COMPRESSION="${2:-none}"
2976 ISO_NAME="${3:-slitaz}"
2977 check_root
2978 # Start info
2979 title 'Write filesystem to ISO'
2980 longline "The command writeiso will write the current filesystem into a \
2981 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2982 newline
2983 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2985 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2986 # Save some space
2987 rm -rf /var/cache/tazpkg/*
2988 rm -f /var/lib/tazpkg/*.bak
2989 rm -rf $DISTRO
2991 # Optionally remove sound card selection and screen resolution.
2992 if [ -z $LaunchedByTazpanel ]; then
2993 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2994 case $anser in
2995 y)
2996 action 'Removing current sound card and screen configurations...'
2997 rm -f /var/lib/sound-card-driver
2998 rm -f /var/lib/alsa/asound.state
2999 rm -f /etc/X11/xorg.conf ;;
3000 *)
3001 action 'Keeping current sound card and screen configurations...' ;;
3002 esac
3003 status
3004 newline
3006 # Optionally remove i18n settings
3007 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3008 case $anser in
3009 y)
3010 action 'Removing current locale/keymap settings...'
3011 newline > /etc/locale.conf
3012 newline > /etc/keymap.conf ;;
3013 *)
3014 action 'Keeping current locale/keymap settings...' ;;
3015 esac
3016 status
3017 fi
3019 # Clean-up files by default
3020 newline > /etc/udev/rules.d/70-persistent-net.rules
3021 newline > /etc/udev/rules.d/70-persistant-cd.rules
3023 # Create list of files including default user files since it is defined in /etc/passwd
3024 # and some new users might have been added.
3025 cd /
3026 echo 'init' > /tmp/list
3027 for dir in bin etc sbin var dev lib root usr home opt; do
3028 [ -d $dir ] && find $dir
3029 done >> /tmp/list
3031 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3032 [ -d $dir ] && echo $dir
3033 done >> /tmp/list
3035 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3037 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3038 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3039 #fi
3040 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3041 touch /var/log/wtmp
3043 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3044 sed -i "/var\/log\/$removelog/d" /tmp/list
3045 done
3047 # Generate initramfs with specified compression and display rootfs
3048 # size in realtime.
3049 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3051 write_initramfs &
3052 sleep 2
3053 cd - > /dev/null
3054 echo -en "\nFilesystem size:"
3055 while [ ! -f /tmp/rootfs ]; do
3056 sleep 1
3057 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3058 done
3059 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3060 echo -e "\n"
3061 rm -f /tmp/rootfs
3063 # Move freshly generated rootfs to the cdrom.
3064 mkdir -p $ROOTCD/boot
3065 mv -f /$INITRAMFS $ROOTCD/boot
3066 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3068 # Now we need the kernel and isolinux files.
3069 copy_from_cd() {
3070 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3071 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3072 unmeta_boot $ROOTCD
3073 umount /media/cdrom
3076 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3077 copy_from_cd;
3078 elif mount | grep /media/cdrom; then
3079 copy_from_cd;
3080 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3081 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3082 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3083 else
3084 touch /tmp/.write-iso-error
3085 longline "When SliTaz is running in RAM the kernel and bootloader \
3086 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3087 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3088 echo -en "----\nENTER to continue..."; read i
3089 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3090 copy_from_cd
3091 fi
3093 # Generate the iso image.
3094 touch /tmp/.write-iso
3095 newline
3096 cd $DISTRO
3097 create_iso $ISO_NAME.iso $ROOTCD
3098 action 'Creating the ISO md5sum...'
3099 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3100 status
3102 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3103 rm -f /tmp/.write-iso
3105 if [ -z $LaunchedByTazpanel ]; then
3106 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3107 case $anser in
3108 y)
3109 umount /dev/cdrom 2>/dev/null
3110 eject
3111 echo -n "Please insert a blank CD-ROM and press ENTER..."
3112 read i && sleep 2
3113 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3114 echo -en "----\nENTER to continue..."; read i ;;
3115 *)
3116 exit 0 ;;
3117 esac
3118 fi
3119 ;;
3122 burn-iso)
3123 # Guess CD-ROM device, ask user and burn the ISO.
3125 check_root
3126 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3127 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3128 # We can specify an alternative ISO from the cmdline.
3129 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3130 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3132 title 'Tazlito burn ISO'
3133 echo "CD-ROM device : /dev/$DRIVE_NAME"
3134 echo "Drive speed : $DRIVE_SPEED"
3135 echo "ISO image : $iso"
3136 footer
3138 case $(yesorno 'Burn ISO image?' 'n') in
3139 y)
3140 title 'Starting Wodim to burn the ISO...'
3141 sleep 2
3142 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3143 footer 'ISO image is burned to CD-ROM.'
3144 ;;
3145 *)
3146 die 'Exiting. No ISO burned.'
3147 ;;
3148 esac
3149 ;;
3152 merge)
3153 # Merge multiple rootfs into one iso.
3155 if [ -z "$2" ]; then
3156 cat <<EOT
3157 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3159 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3160 i.e: rootfsN is a subset of rootfsN-1
3161 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3162 The boot loader will select the rootfs according to the RAM size detected.
3164 Example:
3165 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3167 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3168 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3170 EOT
3171 exit 2
3172 fi
3174 shift # skip merge
3175 append="$1 slitaz1"
3176 shift # skip size1
3177 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3179 ISO=$1.merged
3181 # Extract filesystems
3182 action 'Mounting %s' "$1"
3183 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3184 status || cleanup_merge
3186 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3187 make_bzImage_hardlink $TMP_DIR/iso/boot
3188 umount -d $TMP_DIR/mnt
3189 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3190 _ '%s is already a merged iso. Aborting.' "$1"
3191 cleanup_merge
3192 fi
3193 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3194 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3195 if [ ! -f /boot/isolinux/ifmem.c32 -a
3196 ! -f /boot/isolinux/c32box.c32 ]; then
3197 cat <<EOT
3198 No file /boot/isolinux/ifmem.c32
3199 Please install syslinux package !
3200 EOT
3201 rm -rf $TMP_DIR
3202 exit 1
3203 fi
3204 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3205 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3206 fi
3208 action 'Extracting %s' 'iso/rootfs.gz'
3209 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3210 [ -d $TMP_DIR/rootfs1/etc ]
3211 status || cleanup_merge
3213 n=1
3214 while [ -n "$2" ]; do
3215 shift # skip rootfs N-1
3216 p=$n
3217 n=$(($n + 1))
3218 append="$append $1 slitaz$n"
3219 shift # skip size N
3220 mkdir -p $TMP_DIR/rootfs$n
3222 action 'Extracting %s' "$1"
3223 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3224 [ -d "$TMP_DIR/rootfs$n/etc" ]
3225 status || cleanup_merge
3227 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3228 action 'Creating %s' "rootfs$p.gz"
3229 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3230 status
3231 done
3232 action 'Creating %s' "rootfs$n.gz"
3233 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3234 status
3235 rm -f $TMP_DIR/iso/boot/rootfs.gz
3236 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3237 create_iso $ISO $TMP_DIR/iso
3238 rm -rf $TMP_DIR
3239 ;;
3242 repack)
3243 # Repack an iso with maximum lzma compression ratio.
3245 ISO=$2
3246 mkdir -p $TMP_DIR/mnt
3248 # Extract filesystems
3249 action 'Mounting %s' "$ISO"
3250 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3251 status || cleanup_merge
3253 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3254 umount -d $TMP_DIR/mnt
3256 for i in $TMP_DIR/iso/boot/rootfs* ; do
3257 action 'Repacking %s' "$(basename $i)"
3258 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3259 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3260 align_to_32bits $i
3261 status
3262 done
3264 create_iso $ISO $TMP_DIR/iso
3265 rm -rf $TMP_DIR
3266 ;;
3269 build-loram)
3270 # Build a Live CD for low RAM systems.
3272 ISO="$2"
3273 OUTPUT="$3"
3274 [ -z "$3" ] && \
3275 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3276 mkdir -p "$TMP_DIR/iso"
3277 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3278 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3279 if ! check_iso_for_loram ; then
3280 umount -d "$TMP_DIR/iso"
3281 die "$ISO is not a valid SliTaz live CD. Abort."
3282 fi
3283 case "$4" in
3284 cdrom) build_loram_cdrom ;;
3285 http) build_loram_http ;;
3286 *) build_loram_ram "$5" ;;
3287 esac
3288 umount $TMP_DIR/iso # no -d: needs /proc
3289 losetup -d $loopdev
3290 rm -rf $TMP_DIR
3291 ;;
3294 emu-iso)
3295 # Emulate an ISO image with Qemu.
3296 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3297 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3298 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3299 echo -e "\nStarting Qemu emulator:\n"
3300 echo -e "qemu $QEMU_OPTS $iso\n"
3301 qemu $QEMU_OPTS $iso
3302 ;;
3305 deduplicate)
3306 # Deduplicate files in a tree
3307 shift
3308 deduplicate "$@"
3309 ;;
3312 usage|*)
3313 # Print usage also for all unknown commands.
3314 usage
3315 ;;
3316 esac
3318 exit 0