tazlito view tazlito @ rev 504

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