tazlito view tazlito @ rev 531

tazlito: hexdump -R may not by supported in busybox
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Jun 18 13:45:55 2021 +0000 (2021-06-18)
parents 668f2e7befb0
children c869b6f17992
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)/"
37 efi_img="efi/esp.img"
39 log='/var/log/tazlito.log'
40 if [ $(id -u) -eq 0 ]; then
41 newline > $log
42 fi
45 cleanup() {
46 if [ -d "$TMP_MNT" ]; then
47 umount $TMP_MNT
48 rmdir $TMP_MNT
49 rm -f /boot
50 fi
51 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
52 [ -d "$flv_dir" ] && rm -r "$flv_dir"
53 }
56 # Report error and finish work
58 die() {
59 emsg "<n>$(longline "$@")<n> " >&2
60 cleanup
61 exit 1
62 }
65 # Run Tazlito module
66 module() {
67 local mod="$1"; shift
68 /usr/libexec/tazlito/$mod $@
69 }
73 # Try to include config file, continue if command is gen-config or exit.
74 # The main config used by default is in /etc/tazlito.
75 # Specific distro config file can be put in a distro tree.
76 for i in /etc/tazlito "$TOP_DIR"; do
77 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
78 done
80 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
81 die 'Unable to find any configuration file.' \
82 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
84 . $CONFIG_FILE
86 # While Tazpkg is not used the default mirror URL file does not exist
87 # and user can't recharge the list of flavors.
88 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
90 # Set the rootfs and rootcd path with $DISTRO
91 # configuration variable.
92 ROOTFS="$DISTRO/rootfs"
93 ROOTCD="$DISTRO/rootcd"
98 #####################
99 # Tazlito functions #
100 #####################
103 # Print the usage.
105 usage () {
106 [ $(basename $0) = 'tazlito' ] && cat <<EOT
108 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
110 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
112 $(boldify "Commands:")
113 EOT
114 optlist "\
115 usage Print this short usage.
116 stats View Tazlito and distro configuration statistics.
117 list-addfiles Simple list of additional files in the rootfs.
118 gen-config Generate a new configuration file for a distro.
119 configure Configure the main config file or a specific tazlito.conf.
120 gen-iso Generate a new ISO from a distro tree.
121 gen-initiso Generate a new initramfs and ISO from the distro tree.
122 list-flavors List all flavors available on the mirror.
123 gen-flavor Generate a new Live CD description.
124 gen-liveflavor Generate a Live CD description from current system.
125 show-flavor Show Live CD description.
126 get-flavor Get a flavor's list of packages (--noup to skip update).
127 upgrade-flavor Update package list to the latest available versions.
128 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
129 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
130 iso2flavor Create a flavor file from a SliTaz ISO image.
131 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
132 gen-distro Generate a Live distro and ISO from a list of packages.
133 clean-distro Remove all files generated by gen-distro.
134 check-distro Help to check if distro is ready to release.
135 writeiso Use running system to generate a bootable ISO (with /home).
136 merge Merge multiple rootfs into one ISO.
137 deduplicate Deduplicate files in a tree.
138 repack Recompress rootfs into ISO with maximum ratio.
139 build-loram Generate a Live CD for low-RAM systems.
140 emu-iso Emulate an ISO image with QEMU.
141 burn-iso Burn ISO image to a CD-ROM using Wodim.
142 "
143 }
146 yesorno() {
147 local answer
148 echo -n "$1 (y=yes, n=no) [$2] " >&2
149 case "$DEFAULT_ANSWER" in
150 Y|y) answer="y";;
151 N|n) answer="n";;
152 *)
153 read -t 30 answer
154 [ -z "$answer" ] && answer="$2"
155 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
156 ;;
157 esac
158 echo "$answer"
159 }
162 field() {
163 grep "^$1" "$2" | \
164 case "$1" in
165 Desc*) sed 's|^.*: *||';;
166 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
167 esac
168 }
171 todomsg() {
172 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
173 }
176 hexdump_R() {
177 sed '/ /!d;s/ |.*//;s| *$||;s| *|\\\\x|g;s|^[^\\]*|busybox echo -en |' | sh
178 }
181 # Download a file from this mirror
183 download_from() {
184 local i mirrors="$1"
185 shift
186 for i in $mirrors; do
187 case "$i" in
188 http://*|ftp://*|https://*)
189 wget -c $i$@ && break;;
190 *)
191 cp $i/$1 . && break;;
192 esac
193 done
194 }
197 # Download a file trying all mirrors
199 download() {
200 local i
201 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
202 download_from "$i" "$@" && break
203 done
204 }
207 # Execute hooks provided by some packages
209 genisohooks() {
210 local here="$(pwd)"
211 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
212 cd $ROOTFS
213 . $i $ROOTCD
214 done
215 cd "$here"
216 }
219 # Echo the package name if the tazpkg is already installed
221 installed_package_name() {
222 local tazpkg="$1" package VERSION EXTRAVERSION
224 # Try to find package name and version to be able
225 # to repack it from installation
226 # A dash (-) can exist in name *and* in version
227 package=${tazpkg%-*}
228 i=$package
229 while true; do
230 unset VERSION EXTRAVERSION
231 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
232 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
233 if [ "$i-$VERSION$EXTRAVERSION" = "$tazpkg" ]; then
234 echo $i
235 break
236 fi
237 case "$i" in
238 *-*);;
239 *) break;;
240 esac
241 i=${i%-*}
242 done
243 }
246 # Check for the rootfs tree.
248 check_rootfs() {
249 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
250 }
253 # Check for the boot dir into the root CD tree.
255 verify_rootcd() {
256 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
257 }
259 set32() {
260 for i in $(seq 0 8 $((${4:-32}-8))); 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 }
265 set64() {
266 for i in $(seq 0 8 24 ; seq 24 -8 0); do
267 printf '\\\\x%02X' $((($2 >> $i) & 255))
268 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
269 }
272 first_block() {
273 busybox stat -m "$1" | sed q
274 }
278 # Force size and location in the 2nd eltorito boot file (/$efi_img)
280 fix_efi_boot_img_size() {
281 local n=$3
282 # Sector count on 16 bits (max 128MB), see offset 6-7 in page 11 of
283 # https://pdos.csail.mit.edu/6.828/2014/readings/boot-cdrom.pdf
284 [ $n -gt 65535 ] && n=65535 && echo "Warning: truncate EFI eltorito boot file"
285 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
286 set32 $((0x1C+2048*$4)) $(($4*4)) $1
287 }
290 # Force the size for the /$efi_img file
292 fix_efi_img_size() {
293 local e=$((0x809C))
294 for i in $(echo ${efi_img//\// } | tr a-z A-Z) ; do
295 local sz=$(get $(($e+10)) "$2" 4)
296 e=$(($(get $(($e+2)) "$2" 4) * 2048))
297 while [ $sz -gt 0 ]; do
298 local len=$(get $e "$2")
299 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
300 2>/dev/null)" = "$i" ] && continue 2
301 [ $len -eq 0 ] && break
302 sz=$(($sz-$len))
303 e=$(($e+$len))
304 done
305 return # not found
306 done
307 set64 $(($e+10)) $1 "$2"
308 }
311 # create /$efi_img to share EFI files with the iso image
313 fixup_uefi_part() {
314 [ -s $2/$efi_img ] || return
315 [ -x $2/$efi_img ] && return
316 local n=$(get 19 "$2/$efi_img")
317 [ $n -eq 0 ] && n=$(get 32 "$2/$efi_img" 4)
318 efiblock=$(first_block "$2/$efi_img")
319 fix_efi_img_size $(($n*512)) $1
320 fix_efi_boot_img_size $1 $2 $n $efiblock
322 # Build file list tree
323 resv=$(get 14 "$2/$efi_img")
324 if [ $(get 57 "$2/$efi_img" 1) -ne 49 ]; then
325 skiphead=5
326 fatsz=$(get 36 "$2/$efi_img" 4)
327 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
328 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
329 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
330 else
331 skiphead=4
332 fatsz=$(get 22 "$2/$efi_img")
333 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
334 fi 2> /dev/null
335 hd "$2/$efi_img" | awk 'BEGIN { skiphead='$skiphead' }
336 {
337 if (skiphead!=0) {
338 if ($1=="*") skiphead--
339 next
340 }
341 if (skipdot!=0) {
342 if (skipdot==2) up[cur]=$13 $12
343 else cur=$13 $12
344 skipdot=0
345 next
346 }
347 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
348 if ($3=="2e") skipdot=2
349 else skipdot=1
350 next
351 }
352 if (gotname!=0) {
353 path=""
354 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
355 if (gotname==2) dir[$13 $12]=name
356 else print $1 " " $13 $12 " " path name
357 gotname=0
358 name=""
359 next
360 }
361 if (s!="") {
362 if (eos==0)
363 for (i=2;i<18;i+=2) {
364 if (i==12) i+=2
365 if ($i=="00") break
366 s=s substr($0,i+60,1)
367 }
368 name=s name
369 s=""
370 eos=0
371 next
372 }
373 if ($13=="0f") {
374 s=""
375 for (i=3;i<16;i+=2) {
376 if (i==13) i+=3
377 if ($i=="00") { eos=1; break }
378 s=s substr($0,i+60,1)
379 }
380 next
381 }
382 if ($13=="10") {
383 name=name "/"
384 gotname=2
385 next
386 }
387 if ($13=="20") {
388 gotname=1
389 next
390 }
391 }
392 ' | ( while read offset cluster file; do
393 cluster=$(($(first_block "$2/$file")-$basecluster))
394 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
395 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
396 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
397 done
399 # Update fat12 or fat16
400 get 57 "$2/$efi_img"
401 dd if="$2/$efi_img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
402 od -An -t u1 -w1 -v
403 ) | awk '
404 {
405 if (state==0) {
406 if ($2=="") {
407 if ($1==12849) fat=12
408 else if ($1==13873) fat=16
409 else fat=32
410 state++
411 }
412 else {
413 for (i=1;i<$2;i++) c[$1+i]=$1+i
414 c[$1+$2]=268435455
415 }
416 next
417 }
418 if (state==1) {
419 prev=$1
420 state++
421 next
422 }
423 if (state==2) {
424 if (fat==12) {
425 n=($1%16)*256+prev
426 if (n!=0) c[pos+1]=n
427 pos++
428 prev=int($1/16)
429 state++
430 next
431 }
432 n=$1*256+prev
433 if (fat==32) {
434 prev=n
435 state=13
436 next
437 }
438 }
439 else if (state==3) {
440 n=$1*16+prev
441 }
442 else if (state==13) {
443 prev=$1*65536+prev
444 state++
445 next
446 }
447 else n=$1*16777216+prev
448 if (n!=0) c[pos+1]=n
449 pos++
450 state=1
451 }
452 END {
453 for (i=1;i<=pos;i+=2) {
454 if (c[i]=="") c[i]=0
455 if (c[i+1]=="") c[i+1]=0
456 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
457 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
458 else {
459 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
460 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
461 }
462 }
463 }' | hexdump_R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
464 conv=notrunc bs=512 > /dev/null 2>&1
465 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
466 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
468 # Cleanup cache
469 umount $2
470 mount -o loop,ro $1 $2
471 }
474 # allocate efi.img stub to share EFI files in the EFI boot partition
476 alloc_uefi_part() {
477 local basedir=$(dirname "$1")/..
478 if [ -s $basedir/$efi_img ]; then
479 chmod +x $basedir/$efi_img
480 return
481 fi
482 local fclust=$({
483 [ -d $basedir/efi ] &&
484 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
485 while [ -s "$1" ]; do
486 local efifile
487 case "$1" in
488 *taz) efifile=bootia32.efi ;;
489 *taz64) efifile=bootx64.efi ;;
490 esac
491 if [ ! -s $basedir/efi/boot/$efifile ] &&
492 [ $(get $((0x82)) "$1") = $((0x4550)) ]; then
493 mkdir -p $basedir/efi/boot 2> /dev/null
494 ln "$1" "$basedir/efi/boot/$efifile"
495 stat -c "%s %n" "$1"
496 for i in $basedir/boot/rootfs* ; do
497 ln "$i" $basedir/efi/boot/ &&
498 stat -c "%s %n" "$i"
499 done 2> /dev/null
500 [ -s $basedir/efi/boot/linux.cmdline ] ||
501 sed 's|/|\\|g' > $basedir/efi/boot/linux.cmdline <<EOT
502 rw root=0x100$(sed '/bzImage/!d;s|.*root=[^ ]*||;q' $basedir/boot/isolinux/isolinux.cfg)\
503 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
504 echo -n " initrd=/EFI/BOOT/$f";done)
505 EOT
506 fi
507 shift
508 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
509 [ ${fclust:-0} -eq 0 ] && return
510 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
511 BEGIN {
512 FS="/"
513 }
514 NF > 1 {
515 d[NF $NF]+=2
516 d[NF-1 $(NF-1)]+=($NF+25)/13
517 }
518 END {
519 for (i in d)
520 n+=int((d[i]+63)/64)
521 print n
522 }')
523 local clusters=$(($fclust+$dclust))
524 if [ $clusters -lt 4068 ]; then
525 fsect=$(((($clusters+2)*3+1023)/1024))
526 ftype="31 32"
527 fhead="F8 FF FF"
528 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
529 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
530 rootsz=2
531 elif [ $clusters -lt 65525 ]; then
532 fsect=$((($clusters+2+255)/256))
533 ftype="31 36"
534 fhead="F8 FF FF FF"
535 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
536 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
537 rootsz=2
538 else
539 fsect=$((($clusters+2+127)/128))
540 ftype="33 32"
541 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
542 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
543 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
544 rootsz=1
545 fi
546 # reserved + fat*2 + root dir + dirs
547 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
548 s=$((($count+$fclust)*4))
549 if [ $s -gt 65535 ]; then
550 size="00 00"
551 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
552 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
553 else
554 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
555 size32="00 00 00 00"
556 fi
557 dd if=/dev/zero bs=512 of=$basedir/$efi_img \
558 count=$s 2> /dev/null
560 # Create boot sector
561 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
562 if [ "$ftype" = "33 32" ]; then
563 hexdump_R <<EOT | dd of=$basedir/$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 $doslabel |
570 0 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/$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/$efi_img \
582 seek=510 bs=1 conv=notrunc
583 hexdump_R <<EOT | dd of=$basedir/$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 $doslabel |
588 0 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/$efi_img \
595 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
596 echo "0 $fhead |" | hexdump_R | dd of=$basedir/$efi_img \
597 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
599 # Add label
600 echo "0 $doslabel 08 |" | hexdump_R | \
601 dd of=$basedir/$efi_img bs=512 conv=notrunc \
602 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
604 mkdir -p /tmp/mnt$$
605 mount -o loop $basedir/$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/$efi_img of=/tmp/fat$$ \
610 skip=$rsect bs=512 count=$fsect 2> /dev/null
611 ( cd $basedir; find efi/boot -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/$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/$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
643 sed -i "s|20[1-9][0-9]|$(date +%Y)|" $2/README $2/index.html
645 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
646 make_bzImage_hardlink $2/boot
647 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
649 while read file; do ls -r $file 2> /dev/null; done << EOT | \
650 awk 'BEGIN { n=100 } { print $1 " " n-- }' > /tmp/cdsort$$
651 $PWD/boot/isolinux/boot.cat
652 $PWD/boot/isolinux/isolinux.bin
653 $PWD/boot/isolinux/isolinux.cfg
654 $PWD/boot/isolinux/vesamenu.c32
655 $PWD/boot/isolinux/splash.*g
656 $PWD/boot/isolinux/i18n.cfg
657 $PWD/boot/isolinux/c32box.c32
658 $PWD/boot/isolinux/kbd
659 $PWD/$efi_img
660 $PWD/boot/bzImage*
661 $PWD/efi/boot/linux.cmdline*
662 $(ls $PWD/boot/rootfs* | tac)
663 EOT
665 action 'Computing md5...'
666 touch $2/boot/isolinux/boot.cat
667 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
668 sort -k 2 > md5sum
669 status
671 cd - >/dev/null
672 title 'Generating ISO image'
674 _ 'Generating %s' "$1"
675 uefi="$(cd $2 ; ls $efi_img 2> /dev/null)"
676 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
677 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
678 -no-emul-boot -boot-load-size 4 -boot-info-table \
679 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
680 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
681 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
682 -A "tazlito $VERSION/$(genisoimage --version)" \
683 -copyright README -P "www.slitaz.org" -no-pad $2
684 rm -f /tmp/cdsort$$
685 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
687 mkdir /tmp/mnt$$
688 mount -o loop,ro $1 /tmp/mnt$$
689 fixup_uefi_part $1 /tmp/mnt$$
690 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
691 ${uefi:+$efi_img} ; do
692 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
693 done
694 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
695 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
696 umount -d /tmp/mnt$$
697 rmdir /tmp/mnt$$
699 if [ -s '/etc/tazlito/info' ]; then
700 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
701 action 'Storing ISO info...'
702 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
703 status
704 fi
705 fi
707 if [ -x '/usr/bin/isohybrid' ]; then
708 action 'Creating hybrid ISO...'
709 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
710 status
711 fi
713 if [ -x '/usr/bin/iso2exe' ]; then
714 echo 'Creating EXE header...'
715 /usr/bin/iso2exe $1 2>/dev/null
716 fi
717 }
720 # Generate a new ISO image using isolinux.
722 gen_livecd_isolinux() {
723 # Some packages may want to alter iso
724 genisohooks iso
725 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
727 # Set date for boot msg.
728 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
729 DATE=$(date +%Y%m%d)
730 action 'Setting build date to: %s...' "$DATE"
731 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
732 status
733 fi
735 cd $DISTRO
736 create_iso $ISO_NAME.iso $ROOTCD
738 action 'Creating the ISO md5sum...'
739 md5sum $ISO_NAME.iso > $ISO_NAME.md5
740 status
742 separator
743 # Some packages may want to alter final iso
744 genisohooks final
745 }
748 lzma_history_bits() {
749 #
750 # This generates an ISO which boots with Qemu but gives
751 # rootfs errors in frugal or liveUSB mode.
752 #
753 # local n
754 # local sz
755 # n=20 # 1Mb
756 # sz=$(du -sk $1 | cut -f1)
757 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
758 # n=$(( $n + 1 ))
759 # sz=$(( $sz / 2 ))
760 # done
761 # echo $n
762 echo ${LZMA_HISTORY_BITS:-24}
763 }
766 lzma_switches() {
767 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
768 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
769 }
772 lzma_set_size() {
773 # Update size field for lzma'd file packed using -si switch
774 return # Need to fix kernel code?
776 local n i
777 n=$(unlzma < $1 | wc -c)
778 for i in $(seq 1 8); do
779 printf '\\\\x%02X' $(($n & 255))
780 n=$(($n >> 8))
781 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
782 }
785 align_to_32bits() {
786 local size=$(stat -c %s ${1:-/dev/null})
787 [ $((${size:-0} & 3)) -ne 0 ] &&
788 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
789 }
792 dolz4() {
793 [ "$(which lz4)" ] || tazpkg get-install lz4
794 lz4 -9 > $1
795 }
798 dogzip() {
799 gzip -9 > $1
800 [ -x /usr/bin/advdef ] && advdef -qz4 $1
801 }
804 # Pack rootfs
806 pack_rootfs() {
807 ( cd $1; find . -print | cpio -o -H newc ) | \
808 case "$COMPRESSION" in
809 none)
810 _ 'Creating %s without compression...' 'initramfs'
811 cat > $2
812 ;;
813 lz4)
814 _ 'Creating %s with lz4 compression...' 'initramfs'
815 dolz4 $2
816 ;;
817 gzip)
818 _ 'Creating %s with gzip compression...' 'initramfs'
819 dogzip $2
820 ;;
821 *)
822 _ 'Creating %s with lzma compression...' 'initramfs'
823 lzma e -si -so $(lzma_switches $1) > $2
824 lzma_set_size $2
825 ;;
826 esac
827 align_to_32bits $2
828 echo 1 > /tmp/rootfs
829 }
832 # Compression functions for writeiso.
834 write_initramfs() {
835 case "$COMPRESSION" in
836 lzma)
837 _n 'Creating %s with lzma compression...' "$INITRAMFS"
838 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
839 align='y'
840 lzma_set_size "/$INITRAMFS"
841 ;;
842 gzip)
843 _ 'Creating %s with gzip compression...' "$INITRAMFS"
844 cpio -o -H newc | dogzip "/$INITRAMFS"
845 ;;
846 lz4)
847 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
848 cpio -o -H newc | dolz4 "/$INITRAMFS"
849 ;;
850 *)
851 # align='y'
852 _ 'Creating %s without compression...' "$INITRAMFS"
853 cpio -o -H newc > "/$INITRAMFS"
854 ;;
855 esac < /tmp/list
856 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
857 echo 1 > /tmp/rootfs
858 }
861 # Deduplicate files (MUST be on the same filesystem).
863 deduplicate() {
864 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
865 (
866 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
867 while read attr inode link file; do
868 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
869 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
870 rm -f "$file"
871 if ln "$old_file" "$file" 2>/dev/null; then
872 hinode="$inode"
873 inode="$old_inode"
874 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
875 save="$(($save+(${attr%%-*}+512)/1024))"
876 continue
877 else
878 cp -p "$old_file" "$file"
879 fi
880 else
881 hinode=""
882 fi
883 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
884 done
885 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
886 )
888 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
889 while read attr inode link file; do
890 echo "$attr-$(readlink "$file" | uuencode -m - | \
891 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
892 done | sort | \
893 (
894 old_attr=""; hardlinks=0;
895 while read attr inode link file; do
896 if [ "$attr" = "$old_attr" ]; then
897 if [ "$inode" != "$old_inode" ]; then
898 rm -f "$file"
899 if ln "$old_file" "$file" 2>/dev/null; then
900 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
901 else
902 cp -a "$old_file" "$file"
903 fi
904 fi
905 else
906 old_file="$file"
907 old_attr="$attr"
908 old_inode="$inode"
909 fi
910 done
911 _ '%s duplicate symlinks.' "$hardlinks"
912 )
913 }
916 # Generate a new initramfs from the root filesystem.
918 gen_initramfs() {
919 # Just in case CTRL+c
920 rm -f $DISTRO/gen
922 # Some packages may want to alter rootfs
923 genisohooks rootfs
924 cd $1
926 # Normalize file time
927 find $1 -newer $1 -exec touch -hr $1 {} \;
929 # Link duplicate files
930 deduplicate
932 # Use lzma if installed. Display rootfs size in realtime.
933 rm -f /tmp/rootfs 2>/dev/null
934 pack_rootfs . $DISTRO/$(basename $1).gz &
935 sleep 2
936 echo -en "\nFilesystem size:"
937 while [ ! -f /tmp/rootfs ]; do
938 sleep 1
939 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
940 done
941 echo -e "\n"
942 rm -f /tmp/rootfs
943 cd $DISTRO
944 mv $(basename $1).gz $ROOTCD/boot
945 }
948 distro_sizes() {
949 if [ -n "$start_time" ]; then
950 time=$(($(date +%s) - $start_time))
951 sec=$time
952 div=$(( ($time + 30) / 60))
953 [ "$div" -ne 0 ] && min="~ ${div}m"
954 _ 'Build time : %ss %s' "$sec" "$min"
955 fi
956 cat <<EOT
957 Build date : $(date +%Y%m%d)
958 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
959 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
960 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
961 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
962 EOT
963 footer "Image is ready: $ISO_NAME.iso"
964 }
967 # Print ISO and rootfs size.
969 distro_stats() {
970 title 'Distro statistics: %s' "$DISTRO"
971 distro_sizes
972 }
975 # Create an empty configuration file.
977 empty_config_file() {
978 cat >> tazlito.conf <<"EOF"
979 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
980 #
982 # Name of the ISO image to generate.
983 ISO_NAME=""
985 # ISO image volume name.
986 VOLUM_NAME="SliTaz"
988 # Name of the preparer.
989 PREPARED="$USER"
991 # Path to the packages repository and the packages.list.
992 PACKAGES_REPOSITORY=""
994 # Path to the distro tree to gen-distro from a list of packages.
995 DISTRO=""
997 # Path to the directory containing additional files
998 # to copy into the rootfs and rootcd of the LiveCD.
999 ADDFILES="$DISTRO/addfiles"
1001 # Default answer for binary question (Y or N)
1002 DEFAULT_ANSWER="ASK"
1004 # Compression utility (lzma, gzip or none)
1005 COMPRESSION="lzma"
1006 EOF
1010 # Extract rootfs.gz somewhere
1012 extract_rootfs() {
1013 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
1014 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1015 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1016 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1017 (cd "$2"; cpio -idm --quiet 2>/dev/null < "$1")
1021 # Extract flavor file to temp directory
1023 extract_flavor() {
1024 # Input: $1 - flavor name to extract;
1025 # $2 = absent/empty: just extract 'outer layer'
1026 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1027 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1028 # Output: temp dir path where flavor was extracted
1029 local f="$1.flavor" from to infos="$1.desc"
1030 [ -f "$f" ] || die "File '$f' not found"
1031 local dir="$(mktemp -d)"
1032 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1034 if [ -n "$2" ]; then
1035 cd $dir
1037 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1039 for i in rootcd rootfs; do
1040 [ -f "$1.$i" ] || continue
1041 mkdir "$i"
1042 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1043 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1044 rm "$1.$i"
1045 done
1046 touch -t 197001010100.00 $1.*
1047 # Info to be stored inside ISO
1048 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1049 rm $1.list*
1051 # Renames
1052 while read from to; do
1053 [ -f "$from" ] || continue
1054 mv "$from" "$to"
1055 done <<EOT
1056 $1.nonfree non-free.list
1057 $1.pkglist packages.list
1058 $1-distro.sh distro.sh
1059 $1.receipt receipt
1060 $1.mirrors mirrors
1061 $1.desc description
1062 EOT
1063 fi
1065 echo $dir
1069 # Pack flavor file from temp directory
1071 pack_flavor() {
1072 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1076 # Remove duplicate files
1078 files_match() {
1079 if [ -d "$1" ]; then
1080 return 1
1082 elif [ -L "$1" ] && [ -L "$2" ]; then
1083 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1085 elif [ -f "$1" ] && [ -f "$2" ]; then
1086 cmp -s "$1" "$2" && return 0
1088 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1089 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1090 return 0
1092 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1093 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1094 return 0
1096 fi 2> /dev/null
1097 return 1
1100 remove_with_path() {
1101 dir="$(dirname $1)"
1102 rm -f "$1"
1103 while rmdir "$dir" 2> /dev/null; do
1104 dir="$(dirname $dir)"
1105 done
1108 mergefs() {
1109 # Note, many packages have files with spaces in the name
1110 IFS=$'\n'
1112 local size1=$(du -hs "$1" | awk '{ print $1 }')
1113 local size2=$(du -hs "$2" | awk '{ print $1 }')
1114 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1116 # merge symlinks files and devices
1117 ( cd "$1"; find ) | \
1118 while read file; do
1119 files_match "$1/$file" "$2/$file" "$file" &&
1120 remove_with_path "$2/$file"
1121 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1122 done
1124 unset IFS
1125 status
1129 cleanup_merge() {
1130 rm -rf $TMP_DIR
1131 exit 1
1135 # Update isolinux config files for multiple rootfs
1137 update_bootconfig() {
1138 local files
1139 action 'Updating boot config files...'
1140 files="$(grep -l 'include common' $1/*.cfg)"
1141 for file in $files; do
1142 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1143 if (/label/) label=$0;
1144 else if (/kernel/) kernel=$0;
1145 else if (/append/) {
1146 i=index($0,"rootfs.gz");
1147 append=substr($0,i+9);
1149 else if (/include/) {
1150 for (i = 1; i <= n; i++) {
1151 print label i
1152 print kernel;
1153 initrd="initrd=/boot/rootfs" n ".gz"
1154 for (j = n - 1; j >= i; j--) {
1155 initrd=initrd ",/boot/rootfs" j ".gz";
1157 printf "\tappend %s%s\n",initrd,append;
1158 print "";
1160 print;
1162 else print;
1163 }' < $file > $file.$$
1164 mv -f $file.$$ $file
1165 done
1166 sel="$(echo $2 | awk '{
1167 for (i=1; i<=NF; i++)
1168 if (i % 2 == 0) printf " slitaz%d", i/2
1169 else printf " %s", $i
1170 }')"
1172 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1174 label slitaz
1175 kernel /boot/isolinux/ifmem.c32
1176 append$sel noram
1178 label noram
1179 config noram.cfg
1181 EOT
1183 # Update vesamenu
1184 if [ -s "$1/isolinux.cfg" ]; then
1185 files="$files $1/isolinux.cfg"
1186 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1187 BEGIN {
1188 kernel = " COM32 c32box.c32"
1191 if (/ROWS/) print "MENU ROWS " n+$3;
1192 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1193 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1194 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1195 else if (/VSHIFT/) {
1196 x = $3-n;
1197 if (x < 0) x = 0;
1198 print "MENU VSHIFT " x;
1200 else if (/rootfs.gz/) {
1201 linux = "";
1202 if (/bzImage/) linux = "linux /boot/bzImage ";
1203 i = index($0, "rootfs.gz");
1204 append = substr($0, i+9);
1205 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1206 printf "\tappend%s noram\n", sel;
1207 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1208 for (i = 1; i <= n; i++) {
1209 print "LABEL slitaz" i
1210 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1211 printf "%s\n", kernel;
1212 initrd = "initrd=/boot/rootfs" n ".gz"
1213 for (j = n - 1; j >= i; j--) {
1214 initrd = initrd ",/boot/rootfs" j ".gz";
1216 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1219 else if (/bzImage/) kernel = $0;
1220 else print;
1221 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1222 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1223 fi
1225 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1226 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1227 cat > $1/noram.cfg <<EOT
1228 implicit 0
1229 prompt 1
1230 timeout 80
1231 $(grep '^F[0-9]' $1/isolinux.cfg)
1233 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1234 say Not enough RAM to boot slitaz. Trying hacker mode...
1235 default hacker
1236 label hacker
1237 KERNEL /boot/bzImage
1238 append rw root=/dev/null vga=normal
1240 label reboot
1241 EOT
1243 if [ -s $1/c32box.c32 ]; then
1244 cat >> $1/noram.cfg <<EOT
1245 COM32 c32box.c32
1246 append reboot
1248 label poweroff
1249 COM32 c32box.c32
1250 append poweroff
1252 EOT
1253 else
1254 echo " com32 reboot.c32" >> $1/noram.cfg
1255 fi
1257 # Restore real label names
1258 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1259 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1260 while read pat; do
1261 sed -i "s/slitaz$pat/" $files
1262 done
1263 status
1267 # Uncompress rootfs or module to stdout
1269 uncompress() {
1270 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1271 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1275 # Install a missing package
1277 install_package() {
1278 if [ -z "$2" ]; then
1279 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1280 else
1281 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1282 fi
1283 case "$answer" in
1284 y)
1285 # We don't want package on host cache.
1286 action 'Getting and installing package: %s' "$1"
1287 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1288 status ;;
1289 *)
1290 return 1 ;;
1291 esac
1295 # Check iso for loram transformation
1297 check_iso_for_loram() {
1298 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1299 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1303 # Remove duplicated files in $1/efi/boot from $1/boot
1305 cleanup_efi_boot() {
1306 for i in $1/$efi_img $1/boot/isolinux/efi.img ; do
1307 [ -s $i ] && [ ! -x $i ] && rm -f $i
1308 done
1309 for i in $1/efi/boot/* ; do
1310 [ -f $i ] || continue
1311 case "$i" in
1312 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1313 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1314 rm $1/efi/boot/linux.cmdline ;;
1315 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1316 rm $1/efi/boot/linux.cmdline* ;;
1317 esac
1318 rm -f $i
1319 rmdir $1/efi/boot && rmdir $1/efi
1320 done 2> /dev/null
1324 # Build initial rootfs for loram ISO ram/cdrom/http
1326 build_initfs() {
1327 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1328 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1329 mirror3.slitaz.org mirror.slitaz.org"
1330 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1331 [ -z "$version" ] && die "Can't find the kernel version." \
1332 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1334 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1335 need_lib=false
1336 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1337 mkdir -p $TMP_DIR/initfs/$i
1338 done
1339 ln -s bin $TMP_DIR/initfs/sbin
1340 ln -s . $TMP_DIR/initfs/usr
1341 for aufs in aufs overlayfs; do
1342 for v in $version ; do
1343 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1344 install_package ${v/*taz/linux}-$aufs $v && continue
1345 done
1346 install_package $aufs $version && break
1347 done || return 1
1348 [ -s /init ] || install_package slitaz-boot-scripts
1349 cp /init $TMP_DIR/initfs/
1350 for v in $version ; do
1351 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1352 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1353 done
1354 if [ "$1" = 'cdrom' ]; then
1355 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1356 else
1357 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1358 for v in $version ; do
1359 if [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; then
1360 install_package linux-squashfs $v || return 1
1361 fi
1362 done
1363 for v in $version ; do
1364 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1365 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1366 done
1367 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1368 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1369 fi
1370 if [ "$1" = 'http' ]; then
1371 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1372 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1373 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1374 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1375 cp -a /dev/fuse $TMP_DIR/initfs/dev
1376 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1377 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1378 else
1379 need_lib=true
1380 fi
1381 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1382 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1383 else
1384 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1385 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1386 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1387 cp -a /lib/librt* $TMP_DIR/initfs/lib
1388 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1389 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1390 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1391 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1392 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1393 need_lib=true
1394 fi
1395 cd $TMP_DIR/fs
1396 echo 'Getting slitaz-release & ethernet modules...'
1397 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1398 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1399 [ -s rootfs* ] || continue
1400 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1401 rm -f rootfs*
1402 done 2>&1 > /dev/null
1403 cd - > /dev/null
1404 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1405 for v in $version ; do
1406 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1407 -type f -name '*.ko*' | while read mod; do
1408 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1409 uncompress $mod > $f
1410 grep -q alias=pci: $f || rm -f $f
1411 done
1412 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1413 f=$(basename $i)..z
1414 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1415 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1416 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1417 for j in $deps; do
1418 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1419 uncompress $mod > $(echo $j | sed s/..z$//)
1420 done
1421 done
1422 done
1423 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"
1424 _n 'List of URLs to insert: '
1425 read -t 30 urliso2
1426 urliso="$urliso2 $urliso"
1427 fi
1428 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1429 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1430 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1431 else
1432 cp /bin/busybox $TMP_DIR/initfs/bin
1433 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1434 cp /sbin/insmod $TMP_DIR/initfs/bin
1435 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1436 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1437 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1438 fi
1439 need_lib=true
1440 fi
1441 bins="sh switch_root"
1442 [ "$(echo ls | chroot $TMP_DIR/initfs busybox sh 2> /dev/null)" ] ||
1443 bins="$($TMP_DIR/initfs/bin/busybox | awk \
1444 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g')"
1445 for i in $bins ; do
1446 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1447 done
1448 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1449 for v in $version ; do
1450 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1451 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1452 done
1453 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1454 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1455 cp -a $i $TMP_DIR/initfs/dev
1456 done
1457 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1458 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1459 cp -a $i $TMP_DIR/initfs/dev
1460 done 2>/dev/null
1461 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1462 cp -a $i $TMP_DIR/initfs/lib
1463 done
1464 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1465 #!/bin/sh
1467 getarg() {
1468 grep -q " \$1=" /proc/cmdline || return 1
1469 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1470 return 0
1473 copy_rootfs() {
1474 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1475 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1476 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1477 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1478 path=/mnt/
1479 return 0
1480 else
1481 rm -f /mnt/rootfs*
1482 return 1
1483 fi
1486 echo "Switching / to tmpfs..."
1487 mount -t proc proc /proc
1488 size="\$(grep rootfssize= < /proc/cmdline | \\
1489 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1490 [ -n "\$size" ] || size="-o size=90%"
1492 mount -t sysfs sysfs /sys
1493 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1494 [ -s \$i ] && continue
1495 echo -en "Probe \$i \\r"
1496 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1497 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1498 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1499 insmod /lib/modules/\$k.ko 2> /dev/null
1500 done
1501 echo "Loading \$i"
1502 insmod \$i 2> /dev/null
1503 break
1504 done
1505 done
1506 umount /sys
1507 while read var default; do
1508 eval \$var=\$default
1509 getarg \$var \$var
1510 done <<EOT
1511 eth eth0
1512 dns 208.67.222.222,208.67.220.220
1513 netmask 255.255.255.0
1514 gw
1515 ip
1516 EOT
1517 grep -q \$eth /proc/net/dev || sh
1518 if [ -n "\$ip" ]; then
1519 ifconfig \$eth \$ip netmask \$netmask up
1520 route add default gateway \$gw
1521 for i in \$(echo \$dns | sed 's/,/ /g'); do
1522 echo "nameserver \$i" >> /etc/resolv.conf
1523 done
1524 else
1525 udhcpc -f -q -s /lib/udhcpc -i \$eth
1526 fi
1527 for i in $urliso ; do
1528 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1529 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"
1530 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1531 done
1532 getarg urliso URLISO
1533 DIR=fs
1534 if getarg loram DIR; then
1535 DEVICE=\${DIR%,*}
1536 DIR=/\${DIR#*,}
1537 fi
1538 mount -t tmpfs \$size tmpfs /mnt
1539 path2=/mnt/.httpfs/
1540 path=/mnt/.cdrom/
1541 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1542 while [ ! -d \$path/boot ]; do
1543 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1544 httpfs \$i \$path2 && echo \$i && break
1545 done
1546 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1547 done
1549 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1550 umount /proc
1551 branch=:/mnt/.cdrom/\$DIR
1552 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1553 branch=
1554 lp=1
1555 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1556 [ -s \$i ] && insmod \$i
1557 done 2> /dev/null
1558 for i in \${path}boot/rootfs?.* ; do
1559 fs=\${i#*root}
1560 branch=\$branch:/mnt/.\$fs
1561 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1562 losetup -o 124 /dev/loop\$lp \$i
1563 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1564 lp=\$((\$lp+1))
1565 done
1566 fi
1567 mkdir -p /mnt/.rw/mnt/.httpfs
1568 while read type opt; do
1569 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1570 [ -s \$i ] && insmod \$i &&
1571 mount -t \$type -o \$opt none /mnt && break 2
1572 done
1573 done <<EOT
1574 aufs br=/mnt/.rw\$branch
1575 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1576 EOT
1577 rm -rf /lib/modules
1578 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1579 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1580 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1581 EOTEOT
1582 chmod +x $TMP_DIR/initfs/init
1583 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1584 [ -s $i ] || continue
1585 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1586 rm -f $i
1587 done 2>/dev/null
1588 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1589 lzma e $TMP_DIR/initfs.gz -si
1590 lzma_set_size $TMP_DIR/initfs.gz
1591 rm -rf $TMP_DIR/initfs
1592 align_to_32bits $TMP_DIR/initfs.gz
1593 return 0
1597 # Move each initramfs to squashfs
1599 build_loram_rootfs() {
1600 rootfs_sizes=""
1601 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1602 mkdir -p $TMP_DIR/fs
1603 cd $TMP_DIR/fs
1604 uncompress $i | cpio -idm
1605 deduplicate
1606 cd - > /dev/null
1607 rootfs=$TMP_DIR/$(basename $i 64)
1608 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1609 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1610 cd $TMP_DIR
1611 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1612 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1613 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1614 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1615 rm -f $rootfs
1616 mv ${rootfs%64}.cpio $rootfs
1617 cd - > /dev/null
1618 rm -rf $TMP_DIR/fs
1619 done
1623 # Move meta boot configuration files to basic configuration files
1624 # because meta loram flavor is useless when rootfs is not loaded in RAM
1626 unmeta_boot() {
1627 local root=${1:-$TMP_DIR/loramiso}
1628 if [ -f $root/boot/isolinux/noram.cfg ]; then
1629 # We keep enough information to do unloram...
1630 [ -s $root/boot/isolinux/common.cfg ] &&
1631 sed -i 's/label slitaz/label orgslitaz/' \
1632 $root/boot/isolinux/common.cfg
1633 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1634 shift
1635 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1636 $root/boot/isolinux/isolinux.cfg
1637 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1638 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1639 $root/boot/isolinux/*.cfg
1640 fi
1644 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1645 # These squashfs may be loaded in RAM at boot time.
1646 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1647 # Meta flavors are converted to normal flavors.
1649 build_loram_cdrom() {
1650 build_initfs cdrom || return 1
1651 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1652 cleanup_efi_boot $TMP_DIR/loramiso
1653 mkdir $TMP_DIR/loramiso/fs
1654 cd $TMP_DIR/loramiso/fs
1655 for i in $( ls ../boot/root* | sort -r ) ; do
1656 uncompress $i | cpio -idmu
1657 rm -f $i
1658 done
1659 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1660 cd - >/dev/null
1661 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1662 unmeta_boot
1663 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1664 busybox sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1665 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1666 busybox sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' \
1667 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1668 create_iso $OUTPUT $TMP_DIR/loramiso
1672 # Create http bootstrap to load and remove loram_cdrom
1673 # Meta flavors are converted to normal flavors.
1675 build_loram_http() {
1676 build_initfs http || return 1
1677 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1678 cleanup_efi_boot $TMP_DIR/loramiso
1679 rm -f $TMP_DIR/loramiso/boot/rootfs*
1680 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1681 unmeta_boot
1682 create_iso $OUTPUT $TMP_DIR/loramiso
1686 # Update meta flavor selection sizes.
1687 # Reduce sizes with rootfs gains.
1689 update_metaiso_sizes() {
1690 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1691 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1692 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1693 do
1694 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1695 local sizes="$rootfs_sizes"
1696 local new
1697 set -- $append
1698 shift
1699 [ "$1" = "ifmem" ] && shift
1700 new=""
1701 while [ -n "$2" ]; do
1702 local s
1703 case "$1" in
1704 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1705 *M) s=$(( ${1%M} * 1024 ));;
1706 *) s=${1%K};;
1707 esac
1708 sizes=${sizes#* }
1709 for i in $sizes ; do
1710 s=$(( $s - $i ))
1711 done
1712 new="$new $s $2"
1713 shift 2
1714 done
1715 busybox sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1716 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1717 busybox sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1718 busybox sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1719 busybox sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' $cfg
1720 done
1724 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1725 # Meta flavor selection sizes are updated.
1727 build_loram_ram() {
1728 build_initfs ram || return 1
1729 build_loram_rootfs "$1"
1730 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1731 cleanup_efi_boot $TMP_DIR/loramiso
1732 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1733 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1734 update_metaiso_sizes
1735 create_iso $OUTPUT $TMP_DIR/loramiso
1739 # Remove files installed by packages
1741 find_flavor_rootfs() {
1742 for i in $1/etc/tazlito/*.extract; do
1743 [ -e $i ] || continue
1744 chroot $1 /bin/sh ${i#$1}
1745 done
1747 # Clean hardlinks and files patched by genisofs in /boot
1748 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1749 rm -f $1/boot/$i*
1750 done
1752 # Clean files generated in post_install
1753 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1754 $1/dev/core $1/dev/fd $1/dev/std*
1756 # Verify md5
1757 cat $1$INSTALLED/*/md5sum | \
1758 while read md5 file; do
1759 [ -e "$1$file" ] || continue
1760 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1761 rm -f "$1$file"
1762 done
1764 # Check configuration files
1765 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1766 [ -e $i ] || continue
1767 mkdir /tmp/volatile$$
1768 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1769 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1770 while read file ; do
1771 [ -e "$1/$file" ] || continue
1772 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1773 done
1774 rm -rf /tmp/volatile$$
1775 done
1777 # Remove other files blindly
1778 for i in $1$INSTALLED/*/files.list; do
1779 while read file; do
1780 [ "$1$file" -nt "$i" ] && continue
1781 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1782 [ -d "$1$file" ] || rm -f "$1$file"
1783 done < $i
1784 done
1786 # Remove tazpkg files and tmp files
1787 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1788 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1789 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1790 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1791 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1793 # Cleanup directory tree
1794 cd $1
1795 find * -type d | sort -r | while read dir; do
1796 rmdir "$dir" 2>/dev/null
1797 done
1798 cd - > /dev/null
1802 # Get byte(s) from a binary file
1804 get() {
1805 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1809 # Get cpio flavor info from the ISO image
1811 flavordata() {
1812 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1813 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1817 # Restore undigest mirrors
1819 restore_mirrors() {
1820 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1821 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1823 action 'Restoring mirrors...'
1824 if [ -d "$undigest.bak" ]; then
1825 [ -d "$undigest" ] && rm -r "$undigest"
1826 mv "$undigest.bak" "$undigest"
1827 fi
1828 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1829 :; status
1833 # Setup undigest mirrors
1835 setup_mirrors() {
1836 # Setup mirrors in plain system or in chroot (with variable root=)
1837 local mirrorlist="$1" fresh repacked
1838 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1840 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1841 restore_mirrors
1843 _ 'Setting up mirrors for %s...' "$root/"
1844 # Backing up current undigest mirrors and priority
1845 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1846 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1847 rm -rf '/var/www/tazlito/'
1848 mkdir -p '/var/www/tazlito/'
1850 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1851 fresh='/home/slitaz/packages'
1852 if [ -d "$fresh" ]; then
1853 # Setup first undigest mirror
1854 mkdir -p "$undigest/fresh"
1855 echo "$fresh" > "$undigest/fresh/mirror"
1856 echo 'fresh' >> "$priority"
1857 # Rebuild mirror DB if needed
1858 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1859 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1860 tazpkg mkdb "$fresh" --forced --root=''
1861 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1862 fi
1864 # Repacked packages: high priority
1865 repacked="$PACKAGES_REPOSITORY"
1866 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1867 # According to Tazlito setup file (tazlito.conf):
1868 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1869 # or
1870 # WORK_DIR="/home/slitaz"
1871 # and
1872 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1873 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1875 # Setup second undigest mirror
1876 mkdir -p "$undigest/repacked"
1877 echo "$repacked" > "$undigest/repacked/mirror"
1878 echo 'repacked' >> "$priority"
1879 # Rebuild mirror DB if needed
1880 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1881 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1882 tazpkg mkdb "$repacked" --forced --root=''
1883 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1884 fi
1886 # All repositories listed in mirrors list: normal priority
1887 [ -e "$mirrorlist" ] && \
1888 while read mirror; do
1889 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1890 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1891 mkdir -p "$undigest/$mirrorid"
1892 echo "$mirror" > "$undigest/$mirrorid/mirror"
1893 echo "$mirrorid" >> "$priority"
1894 done < "$mirrorlist"
1896 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1898 # Show list of mirrors
1899 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1900 function show(num, name, url) {
1901 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1904 num++;
1905 "cat " db "/undigest/" $0 "/mirror" | getline url;
1906 show(num, $0, url);
1908 END {
1909 num++;
1910 "cat " db "/mirror" | getline url;
1911 show(num, "main", url);
1912 }' "$priority"
1914 tazpkg recharge --quiet >/dev/null
1918 # Get list of 'packages.info' lists using priority
1920 pi_lists() {
1921 local pi
1922 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1923 local priority="$root$LOCALSTATE/priority"
1924 local undigest="$root$LOCALSTATE/undigest"
1927 [ -s "$priority" ] && cat "$priority"
1928 echo 'main'
1929 [ -d "$undigest" ] && ls "$undigest"
1930 } | awk -vun="$undigest/" '
1932 if (arr[$0] != 1) {
1933 arr[$0] = 1;
1934 print un $0 "/packages.info";
1936 }' | sed 's|/undigest/main||' | \
1937 while read pi; do
1938 [ -e "$pi" ] && echo "$pi"
1939 done
1943 # Strip versions from packages list
1945 strip_versions() {
1946 if [ -n "$stripped" ]; then
1947 action 'Consider list %s already stripped' "$(basename "$1")"
1948 status
1949 return 0
1950 fi
1951 action 'Strip versions from list %s...' "$(basename "$1")"
1952 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1953 [ -f "$in_list" ] || die "List '$in_list' not found."
1955 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1956 awk '
1958 if (FILENAME ~ "packages.info") {
1959 # Collect package names
1960 FS = "\t"; pkg[$1] = 1;
1961 } else {
1962 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1963 while (NF > 1 && ! pkg[$0])
1964 NF --;
1965 printf "%s\n", $0;
1967 }' $(pi_lists) "$in_list" > "$tmp_list"
1969 cat "$tmp_list" > "$in_list"
1970 rm "$tmp_list"
1971 status
1975 # Display list of unknown packages (informative)
1977 display_unknown() {
1978 [ -s "$1" ] || return
1979 echo "Unknown packages:" >&2
1980 cat "$1" >&2
1981 rm "$1"
1985 # Display warnings about critical packages absent (informative)
1987 display_warn() {
1988 [ -s "$1" ] || return
1989 echo "Absent critical packages:" >&2
1990 cat "$1" >&2
1991 rm "$1"
1992 echo "Probably ISO image will be unusable."
1996 # Install packages to rootfs
1998 install_list_to_rootfs() {
1999 local list="$1" rootfs="$2" pkg i ii
2000 local undigest="$rootfs/var/lib/tazpkg/undigest"
2002 # initial tazpkg setup in empty rootfs
2003 tazpkg --root=$rootfs >/dev/null 2>&1
2004 # pass current 'mirror' to the rootfs
2005 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
2006 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
2007 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
2008 # link rootfs packages cache to the regular packages cache
2009 rm -r "$rootfs/var/cache/tazpkg"
2010 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
2012 setup_mirrors mirrors
2014 # Just in case if flavor doesn't contain "tazlito" package
2015 mkdir -p "$rootfs/etc/tazlito"
2017 newline
2019 # Choose detailed log with --detailed
2020 if [ -n "$detailed" ]; then
2021 while read pkg; do
2022 separator '-'
2023 echo $pkg
2024 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2025 done < $list
2026 separator '='
2027 else
2028 while read pkg; do
2029 action 'Installing package: %s' "$pkg"
2030 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2031 status
2032 done < $list
2033 fi
2034 newline
2036 restore_mirrors
2037 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2038 for i in fresh repacked; do
2039 ii="$undigest/$i"
2040 [ -d "$ii" ] && rm -rf "$ii"
2041 ii="$rootfs/var/lib/tazpkg/priority"
2042 if [ -f "$ii" ]; then
2043 sed -i "/$i/d" "$ii"
2044 [ -s "$ii" ] || rm "$ii"
2045 fi
2046 done
2047 [ -d "$undigest" ] && \
2048 for i in $(find "$undigest" -type f); do
2049 # Remove all undigest PKGDB files but 'mirror'
2050 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2051 done
2052 [ -d "$undigest" ] && \
2053 rmdir --ignore-fail-on-non-empty "$undigest"
2055 # Un-link packages cache
2056 rm "$rootfs/var/cache/tazpkg"
2058 # Clean /var/lib/tazpkg
2059 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2065 ####################
2066 # Tazlito commands #
2067 ####################
2069 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2070 case "$0" in
2071 *reduplicate)
2072 find ${@:-.} ! -type d -links +1 \
2073 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2074 exit 0 ;;
2075 *deduplicate)
2076 deduplicate "$@"
2077 exit 0 ;;
2078 esac
2081 case "$COMMAND" in
2082 stats)
2083 # Tazlito general statistics from the config file.
2085 title 'Tazlito statistics'
2086 optlist "\
2087 Config file : $CONFIG_FILE
2088 ISO name : $ISO_NAME.iso
2089 Volume name : $VOLUM_NAME
2090 Prepared : $PREPARED
2091 Packages repository : $PACKAGES_REPOSITORY
2092 Distro directory : $DISTRO
2093 Additional files : $ADDFILES
2094 " | sed '/: $/d'
2095 footer
2096 ;;
2099 list-addfiles)
2100 # Simple list of additional files in the rootfs
2101 newline
2102 if [ -d "$ADDFILES/rootfs" ]; then
2103 cd $ADDFILES
2104 find rootfs -type f
2105 else
2106 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2107 fi
2108 newline
2109 ;;
2112 gen-config)
2113 # Generate a new config file in the current dir or the specified
2114 # directory by $2.
2116 if [ -n "$2" ]; then
2117 mkdir -p "$2" && cd "$2"
2118 fi
2120 newline
2121 action 'Generating empty tazlito.conf...'
2122 empty_config_file
2123 status
2125 separator
2126 if [ -f 'tazlito.conf' ] ; then
2127 _ 'Configuration file is ready to edit.'
2128 _ 'File location: %s' "$(pwd)/tazlito.conf"
2129 newline
2130 fi
2131 ;;
2134 configure)
2135 # Configure a tazlito.conf config file. Start by getting
2136 # a empty config file and sed it.
2138 if [ -f 'tazlito.conf' ]; then
2139 rm tazlito.conf
2140 else
2141 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2142 'or in the same directory of the file you want to configure.'
2143 cd /etc
2144 fi
2146 empty_config_file
2148 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2150 # ISO name.
2151 echo -n "ISO name : " ; read answer
2152 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2153 # Volume name.
2154 echo -n "Volume name : " ; read answer
2155 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2156 # Packages repository.
2157 echo -n "Packages repository : " ; read answer
2158 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2159 # Distro path.
2160 echo -n "Distro path : " ; read answer
2161 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2162 footer "Config file is ready to use."
2163 echo 'You can now extract an ISO or generate a distro.'
2164 newline
2165 ;;
2168 gen-iso)
2169 # Simply generate a new iso.
2171 check_root
2172 verify_rootcd
2173 gen_livecd_isolinux
2174 distro_stats
2175 ;;
2178 gen-initiso)
2179 # Simply generate a new initramfs with a new iso.
2181 check_root
2182 verify_rootcd
2183 gen_initramfs "$ROOTFS"
2184 gen_livecd_isolinux
2185 distro_stats
2186 ;;
2189 extract-distro|extract-iso)
2190 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2192 check_root
2193 ISO_IMAGE="$2"
2194 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2195 'Example:\n tazlito image.iso /path/target'
2197 # Set the distro path by checking for $3 on cmdline.
2198 TARGET="${3:-$DISTRO}"
2200 # Exit if existing distro is found.
2201 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2202 'Please clean the distro tree or change directory path.'
2204 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2206 # Start to mount the ISO.
2207 action 'Mounting ISO image...'
2208 mkdir -p "$TMP_DIR"
2209 # Get ISO file size.
2210 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2211 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2212 sleep 2
2213 # Prepare target dir, copy the kernel and the rootfs.
2214 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2215 status
2217 action 'Copying the Linux kernel...'
2218 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2219 make_bzImage_hardlink "$TARGET/rootcd/boot"
2220 else
2221 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2222 fi
2223 status
2225 for i in $(ls $TMP_DIR); do
2226 [ "$i" = 'boot' ] && continue
2227 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2228 done
2230 for loader in isolinux syslinux extlinux grub; do
2231 [ -d "$TMP_DIR/boot/$loader" ] || continue
2232 action 'Copying %s files...' "$loader"
2233 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2234 status
2235 done
2237 action 'Copying the rootfs...'
2238 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2239 status
2241 cleanup_efi_boot "$TARGET/rootcd"
2243 # Extract initramfs.
2244 cd "$TARGET/rootfs"
2245 action 'Extracting the rootfs...'
2246 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2247 extract_rootfs "$i" "$TARGET/rootfs"
2248 done
2249 # unpack /usr
2250 for i in etc/tazlito/*.extract; do
2251 [ -f "$i" ] && . $i ../rootcd
2252 done
2253 # Umount and remove temp directory and cd to $TARGET to get stats.
2254 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2255 cd ..
2256 status
2258 newline
2259 separator
2260 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2261 echo "Distro tree : $(pwd)"
2262 echo "Rootfs size : $(du -sh rootfs)"
2263 echo "Rootcd size : $(du -sh rootcd)"
2264 footer
2265 ;;
2268 list-flavors)
2269 # Show available flavors.
2270 list='/etc/tazlito/flavors.list'
2271 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2272 title 'List of flavors'
2273 cat $list
2274 footer
2275 ;;
2278 show-flavor)
2279 # Show flavor descriptions.
2280 set -e
2281 flavor=${2%.flavor}
2282 flv_dir="$(extract_flavor "$flavor")"
2283 desc="$flv_dir/$flavor.desc"
2284 if [ -n "$brief" ]; then
2285 if [ -z "$noheader" ]; then
2286 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2287 separator
2288 fi
2289 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2290 "$(field ISO "$desc")" \
2291 "$(field Rootfs "$desc")" \
2292 "$(field Description "$desc")"
2293 else
2294 separator
2295 cat "$desc"
2296 fi
2297 cleanup
2298 ;;
2301 gen-liveflavor)
2302 # Generate a new flavor from the live system.
2303 FLAVOR=${2%.flavor}
2304 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2306 case "$FLAVOR" in
2307 -?|-h*|--help)
2308 cat <<EOT
2309 SliTaz Live Tool - Version: $VERSION
2311 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2313 $(boldify '<flavor-patch-file> format:')
2314 $(optlist "\
2315 code data
2316 + package to add
2317 - package to remove
2318 ! non-free package to add
2319 ? display message
2320 @ flavor description
2321 ")
2323 $(boldify 'Example:')
2324 $(optlist "\
2325 @ Developer tools for SliTaz maintainers
2326 + slitaz-toolchain
2327 + mercurial
2328 ")
2329 EOT
2330 exit 1
2331 ;;
2332 esac
2333 mv /etc/tazlito/distro-packages.list \
2334 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2335 rm -f distro-packages.list non-free.list 2>/dev/null
2336 tazpkg recharge
2338 DESC=""
2339 [ -n "$3" ] && \
2340 while read action pkg; do
2341 case "$action" in
2342 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2343 -) yes | tazpkg remove $pkg ;;
2344 !) echo $pkg >> non-free.list ;;
2345 @) DESC="$pkg" ;;
2346 \?) echo -en "$pkg"; read action ;;
2347 esac
2348 done < $3
2350 yes '' | tazlito gen-distro
2351 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2352 mv /etc/tazlito/distro-packages.list.$$ \
2353 /etc/tazlito/distro-packages.list 2>/dev/null
2354 ;;
2357 gen-flavor)
2358 # Generate a new flavor from the last ISO image generated
2359 FLAVOR=${2%.flavor}
2360 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2362 title 'Flavor generation'
2363 check_rootfs
2364 FILES="$FLAVOR.pkglist"
2366 action 'Creating file %s...' "$FLAVOR.flavor"
2367 for i in rootcd rootfs; do
2368 if [ -d "$ADDFILES/$i" ] ; then
2369 FILES="$FILES\n$FLAVOR.$i"
2370 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2371 fi
2372 done
2373 status
2375 answer=$(grep -s ^Description $FLAVOR.desc)
2376 answer=${answer#Description : }
2377 if [ -z "$answer" ]; then
2378 echo -n "Description: "
2379 read answer
2380 fi
2382 action 'Compressing flavor %s...' "$FLAVOR"
2383 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2384 echo "Description : $answer" >> $FLAVOR.desc
2385 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2386 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2387 for i in $(ls $ROOTFS$INSTALLED); do
2388 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2389 EXTRAVERSION=""
2390 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2391 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2392 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2393 echo "$i" >> $FLAVOR.nonfree
2394 else
2395 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2396 fi
2397 done
2398 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2399 for i in $LOCALSTATE/undigest/*/mirror ; do
2400 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2401 done
2402 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2403 touch -t 197001010100.00 $FLAVOR.*
2404 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2405 rm $(echo -e $FILES)
2406 status
2408 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2409 ;;
2412 upgrade-flavor)
2413 # Strip versions from pkglist and update estimated numbers in flavor.desc
2414 flavor="${2%.flavor}"
2415 set -e
2416 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2417 set +e
2419 flv_dir="$(extract_flavor "$flavor")"
2421 strip_versions "$flv_dir/$flavor.pkglist"
2423 action 'Updating %s...' "$flavor.desc"
2425 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2426 set -- $(module calc_sizes "$flv_dir" "$flavor")
2427 restore_mirrors >/dev/null
2429 sed -i -e '/Image is ready/d' \
2430 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2431 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2432 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2433 -e "s|\(Packages *:\).*$|\1 $4|" \
2434 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2435 "$flv_dir/$flavor.desc"
2437 pack_flavor "$flv_dir" "$flavor"
2438 status
2439 display_unknown "$flv_dir/err"
2440 display_warn "$flv_dir/warn"
2441 cleanup
2442 ;;
2445 extract-flavor)
2446 # Extract a flavor into $FLAVORS_REPOSITORY
2447 flavor="${2%.flavor}"
2448 set -e
2449 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2450 set +e
2452 action 'Extracting %s...' "$flavor.flavor"
2453 flv_dir="$(extract_flavor "$flavor" full)"
2454 storage="$FLAVORS_REPOSITORY/$flavor"
2456 rm -rf "$storage" 2>/dev/null
2457 mkdir -p "$storage"
2458 cp -a "$flv_dir"/* "$storage"
2459 rm "$storage/description"
2460 status
2462 strip_versions "$storage/packages.list"
2464 cleanup
2465 ;;
2468 pack-flavor)
2469 # Create a flavor from $FLAVORS_REPOSITORY.
2470 flavor=${2%.flavor}
2471 storage="$FLAVORS_REPOSITORY/$flavor"
2473 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2475 action 'Creating flavor %s...' "$flavor"
2476 tmp_dir="$(mktemp -d)"
2478 while read from to; do
2479 [ -s "$storage/$from" ] || continue
2480 cp -a "$storage/$from" "$tmp_dir/$to"
2481 done <<EOT
2482 mirrors $flavor.mirrors
2483 distro.sh $flavor-distro.sh
2484 receipt $flavor.receipt
2485 non-free.list $flavor.nonfree
2486 EOT
2488 # Build the package list.
2489 # It can include a list from another flavor with the keyword @include
2490 if [ -s "$storage/packages.list" ]; then
2491 include=$(grep '^@include' "$storage/packages.list")
2492 if [ -n "$include" ]; then
2493 include=${include#@include }
2494 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2495 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2496 else
2497 echo -e "\nERROR: Can't find include package list from $include\n"
2498 fi
2499 fi
2500 # Generate the final/initial package list
2501 [ -s "$storage/packages.list" ] && \
2502 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2503 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2504 fi
2506 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2507 # Process multi-rootfs flavor
2508 . "$storage/receipt"
2509 set -- $ROOTFS_SELECTION
2510 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2511 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2512 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2514 for i in rootcd rootfs; do
2515 mkdir "$tmp_dir/$i"
2516 # Copy extra files from the first flavor
2517 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2518 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2519 # Overload extra files by meta flavor
2520 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2521 [ -n "$(ls $tmp_dir/$i)" ] &&
2522 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2523 dogzip "$tmp_dir/$flavor.$i"
2524 rm -rf "$tmp_dir/$i"
2525 done
2526 else
2527 # Process plain flavor
2528 for i in rootcd rootfs; do
2529 [ -d "$storage/$i" ] || continue
2530 (cd "$storage/$i";
2531 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2532 done
2533 fi
2535 unset VERSION MAINTAINER ROOTFS_SELECTION
2536 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2537 ROOTFS_SIZE="$1 (estimated)"
2538 INITRAMFS_SIZE="$2 (estimated)"
2539 ISO_SIZE="$3 (estimated)"
2540 PKGNUM="$4"
2541 . "$storage/receipt"
2543 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2544 Flavor : $FLAVOR
2545 Description : $SHORT_DESC
2546 Version : $VERSION
2547 Maintainer : $MAINTAINER
2548 LiveCD RAM size : $FRUGAL_RAM
2549 Rootfs list : $ROOTFS_SELECTION
2550 Build date : $(date '+%Y%m%d at %T')
2551 Packages : $PKGNUM
2552 Rootfs size : $ROOTFS_SIZE
2553 Initramfs size : $INITRAMFS_SIZE
2554 ISO image size : $ISO_SIZE
2555 ================================================================================
2557 EOT
2559 rm -f $tmp_dir/packages.list
2560 pack_flavor "$tmp_dir" "$flavor"
2561 status
2562 display_unknown "$tmp_dir/err"
2563 display_warn "$flv_dir/warn"
2564 cleanup
2565 ;;
2568 get-flavor)
2569 # Get a flavor's files and prepare for gen-distro.
2570 flavor=${2%.flavor}
2571 title 'Preparing %s distro flavor' "$flavor"
2572 set -e
2573 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2574 set +e
2576 action 'Cleaning %s...' "$DISTRO"
2577 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2578 # Clean old files
2579 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2580 [ -f "$i" ] && rm "$i"
2581 done
2582 mkdir -p "$DISTRO"
2583 status
2585 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2587 action 'Extracting flavor %s...' "$flavor.flavor"
2588 flv_dir="$(extract_flavor "$flavor" info)"
2589 cp -a "$flv_dir"/* .
2590 mv packages.list distro-packages.list
2591 mv -f info /etc/tazlito
2592 status
2594 for i in rootcd rootfs; do
2595 if [ -d "$i" ]; then
2596 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2597 fi
2598 done
2600 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2601 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2603 action 'Updating %s...' 'tazlito.conf'
2604 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2605 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2606 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2607 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2608 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2609 status
2611 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2612 cleanup
2613 ;;
2616 iso2flavor)
2617 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2618 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2620 FLAVOR=${3%.flavor}
2621 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2622 mount -o loop,ro $2 $TMP_DIR/iso
2623 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2624 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2625 ! -s $TMP_DIR/flavor/*.desc ]; then
2626 _ 'META flavors are not supported.'
2627 umount -d $TMP_DIR/iso
2628 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2629 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2630 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2631 umount -d $TMP_DIR/iso
2632 else
2633 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2634 uncompress $i | \
2635 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2636 done
2637 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2638 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2639 '/etc/slitaz-release' '/boot/rootfs.gz'
2640 umount -d $TMP_DIR/iso
2641 else
2642 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2643 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2644 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2645 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2646 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2647 umount -d $TMP_DIR/iso
2648 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2649 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2650 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2651 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2652 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2653 < $TMP_DIR/rootfs$INSTALLED.md5
2654 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2655 if [ -s $TMP_DIR/flavor/*desc ]; then
2656 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2657 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2658 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2659 for i in rootfs rootcd ; do
2660 [ -s $TMP_DIR/flavor/*.list$i ] &&
2661 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2662 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2663 done
2664 else
2665 find_flavor_rootfs $TMP_DIR/rootfs
2666 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2667 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2668 for i in rootfs rootcd ; do
2669 [ "$(ls $TMP_DIR/$i)" ] &&
2670 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2671 done
2672 unset VERSION MAINTAINER
2673 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2674 if [ -n "$DESCRIPTION" ]; then
2675 _n 'Flavor version : '; read -t 30 VERSION
2676 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2677 fi
2679 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2680 Flavor : $FLAVOR
2681 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2682 Version : ${VERSION:-1.0}
2683 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2684 LiveCD RAM size : $RAM_SIZE
2685 Build date : $BUILD_DATE
2686 Packages : $PKGCNT
2687 Rootfs size : $ROOTFS_SIZE
2688 Initramfs size : $INITRAMFS_SIZE
2689 ISO image size : $ISO_SIZE
2690 ================================================================================
2692 EOT
2693 longline "Tazlito can't detect each file installed during \
2694 a package post_install. You should extract this flavor (tazlito extract-flavor \
2695 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2696 tree and remove files generated by post_installs.
2697 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2698 repack the flavor (tazlito pack-flavor $FLAVOR)"
2699 fi
2700 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2701 fi
2702 fi
2703 rm -rf $TMP_DIR
2704 ;;
2707 gen-distro)
2708 # Generate a live distro tree with a set of packages.
2710 check_root
2711 start_time=$(date +%s)
2713 # Tazlito options: --iso or --cdrom
2714 CDROM=''
2715 [ -n "$iso" ] && CDROM="-o loop $iso"
2716 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2718 # Check if a package list was specified on cmdline.
2719 if [ -f "$2" ]; then
2720 LIST_NAME="$2"
2721 else
2722 LIST_NAME='distro-packages.list'
2723 fi
2725 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2726 'Please clean the distro tree or change directory path.'
2727 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2728 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2730 # If list not given: build list with all installed packages
2731 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2732 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2733 fi
2735 # Exit if no list name.
2736 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2738 # Start generation.
2739 title 'Tazlito generating a distro'
2741 # Misc checks
2742 mkdir -p "$PACKAGES_REPOSITORY"
2743 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2744 newline
2746 # Mount CD-ROM to be able to repack boot-loader packages
2747 if [ ! -e /boot -a -n "$CDROM" ]; then
2748 mkdir $TMP_MNT
2749 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2750 ln -s "$TMP_MNT/boot" /
2751 if [ ! -d "$ADDFILES/rootcd" ] ; then
2752 mkdir -p "$ADDFILES/rootcd"
2753 for i in $(ls $TMP_MNT); do
2754 [ "$i" = 'boot' ] && continue
2755 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2756 done
2757 fi
2758 else
2759 rmdir "$TMP_MNT"
2760 fi
2761 fi
2763 # Rootfs stuff.
2764 echo 'Preparing the rootfs directory...'
2765 mkdir -p "$ROOTFS"
2766 export root="$ROOTFS"
2767 # pass current 'mirror' to the root
2768 mkdir -p $root/var/lib/tazpkg $root/etc
2769 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2770 cp -f /etc/slitaz-release $root/etc/slitaz-release
2771 strip_versions "$LIST_NAME"
2773 if [ "$REPACK" = 'y' ]; then
2774 # Determine full packages list with all dependencies
2775 tmp_dir="$(mktemp -d)"
2776 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2777 touch "$tmp_dir/full.pkglist"
2778 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2780 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2781 while read pkgname pkgver; do
2782 # Is package in full list?
2783 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2784 # Is package already repacked?
2785 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2786 _ 'Repacking %s...' "$pkgname-$pkgver"
2787 tazpkg repack "$pkgname" --quiet
2788 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2789 status
2790 done
2792 rm -r "$tmp_dir"
2793 fi
2795 if [ -f non-free.list ]; then
2796 # FIXME: working in the ROOTFS chroot?
2797 newline
2798 echo 'Preparing non-free packages...'
2799 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2800 while read pkg ; do
2801 if [ ! -d "$INSTALLED/$pkg" ]; then
2802 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2803 tazpkg get-install get-$pkg
2804 fi
2805 get-$pkg "$ROOTFS"
2806 fi
2807 tazpkg repack $pkg
2808 pkg=$(ls $pkg*.tazpkg)
2809 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2810 mv $pkg $PACKAGES_REPOSITORY
2811 done < non-free.list
2812 fi
2813 cp $LIST_NAME $DISTRO/distro-packages.list
2814 newline
2816 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2818 cd $DISTRO
2819 cp distro-packages.list $ROOTFS/etc/tazlito
2820 # Copy all files from $ADDFILES/rootfs to the rootfs.
2821 if [ -d "$ADDFILES/rootfs" ] ; then
2822 action 'Copying addfiles content to the rootfs...'
2823 cp -a $ADDFILES/rootfs/* $ROOTFS
2824 status
2825 fi
2827 action 'Root filesystem is generated...'; status
2829 # Root CD part.
2830 action 'Preparing the rootcd directory...'
2831 mkdir -p $ROOTCD
2832 status
2834 # Move the boot dir with the Linux kernel from rootfs.
2835 # The efi & boot dirs go directly on the CD.
2836 if [ -d "$ROOTFS/efi" ] ; then
2837 action 'Moving the efi directory...'
2838 mv $ROOTFS/efi $ROOTCD
2839 status
2840 fi
2841 if [ -d "$ROOTFS/boot" ] ; then
2842 action 'Moving the boot directory...'
2843 mv $ROOTFS/boot $ROOTCD
2844 status
2845 fi
2846 cd $DISTRO
2847 # Copy all files from $ADDFILES/rootcd to the rootcd.
2848 if [ -d "$ADDFILES/rootcd" ] ; then
2849 action 'Copying addfiles content to the rootcd...'
2850 cp -a $ADDFILES/rootcd/* $ROOTCD
2851 status
2852 fi
2853 # Execute the distro script used to perform tasks in the rootfs
2854 # before compression. Give rootfs path in arg
2855 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2856 if [ -x "$DISTRO_SCRIPT" ]; then
2857 echo 'Executing distro script...'
2858 sh $DISTRO_SCRIPT $DISTRO
2859 fi
2861 # Execute the custom_rules() found in receipt.
2862 if [ -s "$TOP_DIR/receipt" ]; then
2863 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2864 echo -e "Executing: custom_rules()\n"
2865 . "$TOP_DIR/receipt"
2866 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2867 fi
2868 fi
2870 # Multi-rootfs
2871 if [ -s /etc/tazlito/rootfs.list ]; then
2873 FLAVOR_LIST="$(awk '{
2874 for (i = 2; i <= NF; i+=2)
2875 printf "%s ", $i;
2876 }' /etc/tazlito/rootfs.list)"
2878 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2879 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2880 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2882 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2883 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2884 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2885 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2887 n=0
2888 last=$ROOTFS
2889 while read flavor; do
2890 n=$(($n+1))
2891 mkdir ${ROOTFS}0$n
2892 export root="${ROOTFS}0$n"
2893 # initial tazpkg setup in empty rootfs
2894 tazpkg --root=$root >/dev/null 2>&1
2896 newline
2897 boldify "Building $flavor rootfs..."
2899 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2900 cp "$TOP_DIR/$flavor.flavor" .
2902 if [ ! -s "$flavor.flavor" ]; then
2903 # We may have it in $FLAVORS_REPOSITORY
2904 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2905 tazlito pack-flavor $flavor
2906 else
2907 download $flavor.flavor
2908 fi
2909 fi
2911 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2912 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2913 cp $flavor.pkglist $DISTRO/list-packages0$n
2914 status
2916 strip_versions "$DISTRO/list-packages0$n"
2918 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2920 action 'Updating the boot directory...'
2921 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2922 rm -rf ${ROOTFS}0$n/boot
2924 cd $DISTRO
2925 if [ -s $flavor.rootfs ]; then
2926 _n 'Adding %s rootfs extra files...' "$flavor"
2927 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2928 fi
2930 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2931 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2932 status
2934 rm -f $flavor.flavor install-list
2935 mergefs ${ROOTFS}0$n $last
2936 last=${ROOTFS}0$n
2937 done <<EOT
2938 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2939 EOT
2940 #'
2941 i=$(($n+1))
2942 while [ $n -gt 0 ]; do
2943 mv ${ROOTFS}0$n ${ROOTFS}$i
2944 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2945 gen_initramfs ${ROOTFS}$i
2946 n=$(($n-1))
2947 i=$(($i-1))
2948 export LZMA_HISTORY_BITS=26
2949 done
2950 mv $ROOTFS ${ROOTFS}$i
2951 gen_initramfs ${ROOTFS}$i
2952 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2953 ROOTFS=${ROOTFS}1
2954 else
2955 # Initramfs and ISO image stuff.
2956 gen_initramfs $ROOTFS
2957 fi
2958 gen_livecd_isolinux
2959 distro_stats
2960 cleanup
2961 ;;
2964 clean-distro)
2965 # Remove old distro tree.
2967 check_root
2968 title 'Cleaning: %s' "$DISTRO"
2969 if [ -d "$DISTRO" ] ; then
2970 if [ -d "$ROOTFS" ] ; then
2971 action 'Removing the rootfs...'
2972 rm -f $DISTRO/$INITRAMFS
2973 rm -rf $ROOTFS
2974 status
2975 fi
2976 if [ -d "$ROOTCD" ] ; then
2977 action 'Removing the rootcd...'
2978 rm -rf $ROOTCD
2979 status
2980 fi
2981 action 'Removing eventual ISO image...'
2982 rm -f $DISTRO/$ISO_NAME.iso
2983 rm -f $DISTRO/$ISO_NAME.md5
2984 status
2985 fi
2986 footer
2987 ;;
2990 check-distro)
2991 # Check for a few LiveCD needed files not installed by packages.
2993 # TODO: Remove this function.
2994 # First two files are maintained by tazpkg while it runs on rootfs,
2995 # while last one file should be maintained by tazlito itself.
2996 check_rootfs
2997 title 'Checking distro: %s' "$ROOTFS"
2998 # SliTaz release info.
2999 rel='/etc/slitaz-release'
3000 if [ ! -f "$ROOTFS$rel" ]; then
3001 _ 'Missing release info: %s' "$rel"
3002 else
3003 action 'Release : %s' "$(cat $ROOTFS$rel)"
3004 status
3005 fi
3006 # Tazpkg mirror.
3007 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
3008 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
3009 todomsg
3010 else
3011 action 'Mirror configuration exists...'
3012 status
3013 fi
3014 # Isolinux msg
3015 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
3016 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
3017 todomsg
3018 else
3019 action 'Isolinux message seems good...'
3020 status
3021 fi
3022 footer
3023 ;;
3026 writeiso)
3027 # Writefs to ISO image including /home unlike gen-distro we don't use
3028 # packages to generate a rootfs, we build a compressed rootfs with all
3029 # the current filesystem similar to 'tazusb writefs'.
3031 DISTRO='/home/slitaz/distro'
3032 ROOTCD="$DISTRO/rootcd"
3033 COMPRESSION="${2:-none}"
3034 ISO_NAME="${3:-slitaz}"
3035 check_root
3036 # Start info
3037 title 'Write filesystem to ISO'
3038 longline "The command writeiso will write the current filesystem into a \
3039 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3040 newline
3041 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3043 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3044 # Save some space
3045 rm -rf /var/cache/tazpkg/*
3046 rm -f /var/lib/tazpkg/*.bak
3047 rm -rf $DISTRO
3049 # Optionally remove sound card selection and screen resolution.
3050 if [ -z $LaunchedByTazpanel ]; then
3051 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3052 case $anser in
3053 y)
3054 action 'Removing current sound card and screen configurations...'
3055 rm -f /var/lib/sound-card-driver
3056 rm -f /var/lib/alsa/asound.state
3057 rm -f /etc/X11/xorg.conf ;;
3058 *)
3059 action 'Keeping current sound card and screen configurations...' ;;
3060 esac
3061 status
3062 newline
3064 # Optionally remove i18n settings
3065 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3066 case $anser in
3067 y)
3068 action 'Removing current locale/keymap settings...'
3069 newline > /etc/locale.conf
3070 newline > /etc/keymap.conf ;;
3071 *)
3072 action 'Keeping current locale/keymap settings...' ;;
3073 esac
3074 status
3075 fi
3077 # Clean-up files by default
3078 newline > /etc/udev/rules.d/70-persistent-net.rules
3079 newline > /etc/udev/rules.d/70-persistant-cd.rules
3081 # Create list of files including default user files since it is defined in /etc/passwd
3082 # and some new users might have been added.
3083 cd /
3084 echo 'init' > /tmp/list
3085 for dir in bin etc sbin var dev lib root usr home opt; do
3086 [ -d $dir ] && find $dir
3087 done >> /tmp/list
3089 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3090 [ -d $dir ] && echo $dir
3091 done >> /tmp/list
3093 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3095 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3096 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3097 #fi
3098 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3099 touch /var/log/wtmp
3101 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3102 sed -i "/var\/log\/$removelog/d" /tmp/list
3103 done
3105 # Generate initramfs with specified compression and display rootfs
3106 # size in realtime.
3107 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3109 write_initramfs &
3110 sleep 2
3111 cd - > /dev/null
3112 echo -en "\nFilesystem size:"
3113 while [ ! -f /tmp/rootfs ]; do
3114 sleep 1
3115 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3116 done
3117 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3118 echo -e "\n"
3119 rm -f /tmp/rootfs
3121 # Move freshly generated rootfs to the cdrom.
3122 mkdir -p $ROOTCD/boot
3123 mv -f /$INITRAMFS $ROOTCD/boot
3124 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3126 # Now we need the kernel and isolinux files.
3127 copy_from_cd() {
3128 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3129 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3130 unmeta_boot $ROOTCD
3131 umount /media/cdrom
3134 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3135 copy_from_cd;
3136 elif mount | grep /media/cdrom; then
3137 copy_from_cd;
3138 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3139 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3140 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3141 else
3142 touch /tmp/.write-iso-error
3143 longline "When SliTaz is running in RAM the kernel and bootloader \
3144 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3145 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3146 echo -en "----\nENTER to continue..."; read i
3147 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3148 copy_from_cd
3149 fi
3151 # Generate the iso image.
3152 touch /tmp/.write-iso
3153 newline
3154 cd $DISTRO
3155 create_iso $ISO_NAME.iso $ROOTCD
3156 action 'Creating the ISO md5sum...'
3157 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3158 status
3160 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3161 rm -f /tmp/.write-iso
3163 if [ -z $LaunchedByTazpanel ]; then
3164 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3165 case $anser in
3166 y)
3167 umount /dev/cdrom 2>/dev/null
3168 eject
3169 echo -n "Please insert a blank CD-ROM and press ENTER..."
3170 read i && sleep 2
3171 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3172 echo -en "----\nENTER to continue..."; read i ;;
3173 *)
3174 exit 0 ;;
3175 esac
3176 fi
3177 ;;
3180 burn-iso)
3181 # Guess CD-ROM device, ask user and burn the ISO.
3183 check_root
3184 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3185 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3186 # We can specify an alternative ISO from the cmdline.
3187 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3188 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3190 title 'Tazlito burn ISO'
3191 echo "CD-ROM device : /dev/$DRIVE_NAME"
3192 echo "Drive speed : $DRIVE_SPEED"
3193 echo "ISO image : $iso"
3194 footer
3196 case $(yesorno 'Burn ISO image?' 'n') in
3197 y)
3198 title 'Starting Wodim to burn the ISO...'
3199 sleep 2
3200 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3201 footer 'ISO image is burned to CD-ROM.'
3202 ;;
3203 *)
3204 die 'Exiting. No ISO burned.'
3205 ;;
3206 esac
3207 ;;
3210 merge)
3211 # Merge multiple rootfs into one iso.
3213 if [ -z "$2" ]; then
3214 cat <<EOT
3215 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3217 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3218 i.e: rootfsN is a subset of rootfsN-1
3219 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3220 The boot loader will select the rootfs according to the RAM size detected.
3222 Example:
3223 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3225 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3226 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3228 EOT
3229 exit 2
3230 fi
3232 shift # skip merge
3233 append="$1 slitaz1"
3234 shift # skip size1
3235 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3237 ISO=$1.merged
3239 # Extract filesystems
3240 action 'Mounting %s' "$1"
3241 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3242 status || cleanup_merge
3244 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3245 make_bzImage_hardlink $TMP_DIR/iso/boot
3246 umount -d $TMP_DIR/mnt
3247 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3248 _ '%s is already a merged iso. Aborting.' "$1"
3249 cleanup_merge
3250 fi
3251 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3252 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3253 if [ ! -f /boot/isolinux/ifmem.c32 -a
3254 ! -f /boot/isolinux/c32box.c32 ]; then
3255 cat <<EOT
3256 No file /boot/isolinux/ifmem.c32
3257 Please install syslinux package !
3258 EOT
3259 rm -rf $TMP_DIR
3260 exit 1
3261 fi
3262 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3263 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3264 fi
3266 action 'Extracting %s' 'iso/rootfs.gz'
3267 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3268 [ -d $TMP_DIR/rootfs1/etc ]
3269 status || cleanup_merge
3271 n=1
3272 while [ -n "$2" ]; do
3273 shift # skip rootfs N-1
3274 p=$n
3275 n=$(($n + 1))
3276 append="$append $1 slitaz$n"
3277 shift # skip size N
3278 mkdir -p $TMP_DIR/rootfs$n
3280 action 'Extracting %s' "$1"
3281 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3282 [ -d "$TMP_DIR/rootfs$n/etc" ]
3283 status || cleanup_merge
3285 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3286 action 'Creating %s' "rootfs$p.gz"
3287 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3288 status
3289 done
3290 action 'Creating %s' "rootfs$n.gz"
3291 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3292 status
3293 rm -f $TMP_DIR/iso/boot/rootfs.gz
3294 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3295 create_iso $ISO $TMP_DIR/iso
3296 rm -rf $TMP_DIR
3297 ;;
3300 repack)
3301 # Repack an iso with maximum lzma compression ratio.
3303 ISO=$2
3304 mkdir -p $TMP_DIR/mnt
3306 # Extract filesystems
3307 action 'Mounting %s' "$ISO"
3308 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3309 status || cleanup_merge
3311 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3312 umount -d $TMP_DIR/mnt
3314 for i in $TMP_DIR/iso/boot/rootfs* ; do
3315 action 'Repacking %s' "$(basename $i)"
3316 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3317 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3318 align_to_32bits $i
3319 status
3320 done
3322 create_iso $ISO $TMP_DIR/iso
3323 rm -rf $TMP_DIR
3324 ;;
3327 build-loram)
3328 # Build a Live CD for low RAM systems.
3330 ISO="$2"
3331 OUTPUT="$3"
3332 [ -z "$3" ] && \
3333 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3334 mkdir -p "$TMP_DIR/iso"
3335 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3336 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3337 if ! check_iso_for_loram ; then
3338 umount -d "$TMP_DIR/iso"
3339 die "$ISO is not a valid SliTaz live CD. Abort."
3340 fi
3341 case "$4" in
3342 cdrom) build_loram_cdrom ;;
3343 http) build_loram_http ;;
3344 *) build_loram_ram "$5" ;;
3345 esac
3346 umount $TMP_DIR/iso # no -d: needs /proc
3347 losetup -d $loopdev
3348 rm -rf $TMP_DIR
3349 ;;
3352 emu-iso)
3353 # Emulate an ISO image with Qemu.
3354 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3355 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3356 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3357 echo -e "\nStarting Qemu emulator:\n"
3358 echo -e "qemu $QEMU_OPTS $iso\n"
3359 qemu $QEMU_OPTS $iso
3360 ;;
3363 deduplicate)
3364 # Deduplicate files in a tree
3365 shift
3366 deduplicate "$@"
3367 ;;
3370 usage|*)
3371 # Print usage also for all unknown commands.
3372 usage
3373 ;;
3374 esac
3376 exit 0