tazlito view tazlito @ rev 526

Do not trust video= arg
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Aug 20 07:55:21 2020 +0000 (6 months ago)
parents b32eae972f44
children df946fc43fb0
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2018 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
21 alias stat='busybox stat'
22 alias awk='busybox awk'
24 # Tazlito configuration variables to be shorter
25 # and to use words rather than numbers.
26 COMMAND="$1"
27 LIST_NAME="$2"
28 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
29 TMP_MNT="/media/tazlito-$$-$RANDOM"
30 TOP_DIR="$(pwd)"
31 INITRAMFS='rootfs.gz'
32 LOCALSTATE='/var/lib/tazpkg'
33 INSTALLED="$LOCALSTATE/installed"
34 CACHE_DIR='/var/cache/tazpkg'
35 MIRROR="$LOCALSTATE/mirror"
36 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
38 log='/var/log/tazlito.log'
39 if [ $(id -u) -eq 0 ]; then
40 newline > $log
41 fi
44 cleanup() {
45 if [ -d "$TMP_MNT" ]; then
46 umount $TMP_MNT
47 rmdir $TMP_MNT
48 rm -f /boot
49 fi
50 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
51 [ -d "$flv_dir" ] && rm -r "$flv_dir"
52 }
55 # Report error and finish work
57 die() {
58 emsg "<n>$(longline "$@")<n> " >&2
59 cleanup
60 exit 1
61 }
64 # Run Tazlito module
65 module() {
66 local mod="$1"; shift
67 /usr/libexec/tazlito/$mod $@
68 }
72 # Try to include config file, continue if command is gen-config or exit.
73 # The main config used by default is in /etc/tazlito.
74 # Specific distro config file can be put in a distro tree.
75 for i in /etc/tazlito "$TOP_DIR"; do
76 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
77 done
79 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
80 die 'Unable to find any configuration file.' \
81 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
83 . $CONFIG_FILE
85 # While Tazpkg is not used the default mirror URL file does not exist
86 # and user can't recharge the list of flavors.
87 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
89 # Set the rootfs and rootcd path with $DISTRO
90 # configuration variable.
91 ROOTFS="$DISTRO/rootfs"
92 ROOTCD="$DISTRO/rootcd"
97 #####################
98 # Tazlito functions #
99 #####################
102 # Print the usage.
104 usage () {
105 [ $(basename $0) = 'tazlito' ] && cat <<EOT
107 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
109 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
111 $(boldify "Commands:")
112 EOT
113 optlist "\
114 usage Print this short usage.
115 stats View Tazlito and distro configuration statistics.
116 list-addfiles Simple list of additional files in the rootfs.
117 gen-config Generate a new configuration file for a distro.
118 configure Configure the main config file or a specific tazlito.conf.
119 gen-iso Generate a new ISO from a distro tree.
120 gen-initiso Generate a new initramfs and ISO from the distro tree.
121 list-flavors List all flavors available on the mirror.
122 gen-flavor Generate a new Live CD description.
123 gen-liveflavor Generate a Live CD description from current system.
124 show-flavor Show Live CD description.
125 get-flavor Get a flavor's list of packages (--noup to skip update).
126 upgrade-flavor Update package list to the latest available versions.
127 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
128 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
129 iso2flavor Create a flavor file from a SliTaz ISO image.
130 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
131 gen-distro Generate a Live distro and ISO from a list of packages.
132 clean-distro Remove all files generated by gen-distro.
133 check-distro Help to check if distro is ready to release.
134 writeiso Use running system to generate a bootable ISO (with /home).
135 merge Merge multiple rootfs into one ISO.
136 deduplicate Deduplicate files in a tree.
137 repack Recompress rootfs into ISO with maximum ratio.
138 build-loram Generate a Live CD for low-RAM systems.
139 emu-iso Emulate an ISO image with QEMU.
140 burn-iso Burn ISO image to a CD-ROM using Wodim.
141 "
142 }
145 yesorno() {
146 local answer
147 echo -n "$1 (y=yes, n=no) [$2] " >&2
148 case "$DEFAULT_ANSWER" in
149 Y|y) answer="y";;
150 N|n) answer="n";;
151 *)
152 read -t 30 answer
153 [ -z "$answer" ] && answer="$2"
154 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
155 ;;
156 esac
157 echo "$answer"
158 }
161 field() {
162 grep "^$1" "$2" | \
163 case "$1" in
164 Desc*) sed 's|^.*: *||';;
165 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
166 esac
167 }
170 todomsg() {
171 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
172 }
175 # Download a file from this mirror
177 download_from() {
178 local i mirrors="$1"
179 shift
180 for i in $mirrors; do
181 case "$i" in
182 http://*|ftp://*|https://*)
183 wget -c $i$@ && break;;
184 *)
185 cp $i/$1 . && break;;
186 esac
187 done
188 }
191 # Download a file trying all mirrors
193 download() {
194 local i
195 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
196 download_from "$i" "$@" && break
197 done
198 }
201 # Execute hooks provided by some packages
203 genisohooks() {
204 local here="$(pwd)"
205 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
206 cd $ROOTFS
207 . $i $ROOTCD
208 done
209 cd "$here"
210 }
213 # Echo the package name if the tazpkg is already installed
215 installed_package_name() {
216 local tazpkg="$1" package VERSION EXTRAVERSION
218 # Try to find package name and version to be able
219 # to repack it from installation
220 # A dash (-) can exist in name *and* in version
221 package=${tazpkg%-*}
222 i=$package
223 while true; do
224 unset VERSION EXTRAVERSION
225 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
226 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
227 if [ "$i-$VERSION$EXTRAVERSION" = "$tazpkg" ]; then
228 echo $i
229 break
230 fi
231 case "$i" in
232 *-*);;
233 *) break;;
234 esac
235 i=${i%-*}
236 done
237 }
240 # Check for the rootfs tree.
242 check_rootfs() {
243 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
244 }
247 # Check for the boot dir into the root CD tree.
249 verify_rootcd() {
250 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
251 }
253 set32() {
254 for i in $(seq 0 8 $((${4:-32}-8))); do
255 printf '\\\\x%02X' $((($2 >> $i) & 255))
256 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
257 }
259 set64() {
260 for i in $(seq 0 8 24 ; seq 24 -8 0); do
261 printf '\\\\x%02X' $((($2 >> $i) & 255))
262 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
263 }
266 first_block() {
267 busybox stat -m "$1" | sed q
268 }
272 # Force size and location in the 2nd eltorito boot file (/boot/isolinux/efi.img)
274 fix_efi_boot_img_size() {
275 local n=$3
276 [ $n -gt 65535 ] && n=65535
277 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
278 set32 $((0x1C+2048*$4)) $(($4*4)) $1
279 }
282 # Force the size for the /boot/isolinux/efi.img file
284 fix_efi_img_size() {
285 local e=$((0x809C))
286 for i in BOOT ISOLINUX EFI.IMG ; do
287 local sz=$(get $(($e+10)) "$2" 4)
288 e=$(($(get $(($e+2)) "$2" 4) * 2048))
289 while [ $sz -gt 0 ]; do
290 local len=$(get $e "$2")
291 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
292 2>/dev/null)" = "$i" ] && continue 2
293 [ $len -eq 0 ] && break
294 sz=$(($sz-$len))
295 e=$(($e+$len))
296 done
297 return # not found
298 done
299 set64 $(($e+10)) $1 "$2"
300 }
303 # create /boot/isolinux/efi.img to share EFI files with the iso image
305 fixup_uefi_part() {
306 [ -s $2/boot/isolinux/efi.img ] || return
307 [ -x $2/boot/isolinux/efi.img ] && return
308 local n=$(get 19 "$2/boot/isolinux/efi.img")
309 [ $n -eq 0 ] && n=$(get 32 "$2/boot/isolinux/efi.img" 4)
310 efiblock=$(first_block "$2/boot/isolinux/efi.img")
311 fix_efi_img_size $(($n*512)) $1
312 fix_efi_boot_img_size $1 $2 $n $efiblock
314 # Build file list tree
315 resv=$(get 14 "$2/boot/isolinux/efi.img")
316 if [ $(get 57 "$2/boot/isolinux/efi.img" 1) -ne 49 ]; then
317 skiphead=5
318 fatsz=$(get 36 "$2/boot/isolinux/efi.img" 4)
319 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
320 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
321 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
322 else
323 skiphead=4
324 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
325 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
326 fi 2> /dev/null
327 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead='$skiphead' }
328 {
329 if (skiphead!=0) {
330 if ($1=="*") skiphead--
331 next
332 }
333 if (skipdot!=0) {
334 if (skipdot==2) up[cur]=$13 $12
335 else cur=$13 $12
336 skipdot=0
337 next
338 }
339 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
340 if ($3=="2e") skipdot=2
341 else skipdot=1
342 next
343 }
344 if (gotname!=0) {
345 path=""
346 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
347 if (gotname==2) dir[$13 $12]=name
348 else print $1 " " $13 $12 " " path name
349 gotname=0
350 name=""
351 next
352 }
353 if (s!="") {
354 if (eos==0)
355 for (i=2;i<18;i+=2) {
356 if (i==12) i+=2
357 if ($i=="00") break
358 s=s substr($0,i+60,1)
359 }
360 name=s name
361 s=""
362 eos=0
363 next
364 }
365 if ($13=="0f") {
366 s=""
367 for (i=3;i<16;i+=2) {
368 if (i==13) i+=3
369 if ($i=="00") { eos=1; break }
370 s=s substr($0,i+60,1)
371 }
372 next
373 }
374 if ($13=="10") {
375 name=name "/"
376 gotname=2
377 next
378 }
379 if ($13=="20") {
380 gotname=1
381 next
382 }
383 }
384 ' | ( while read offset cluster file; do
385 cluster=$(($(first_block "$2/$file")-$basecluster))
386 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
387 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
388 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
389 done
391 # Update fat12 or fat16
392 get 57 "$2/boot/isolinux/efi.img"
393 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
394 od -An -t u1 -w1 -v
395 ) | awk '
396 {
397 if (state==0) {
398 if ($2=="") {
399 if ($1==12849) fat=12
400 else if ($1==13873) fat=16
401 else fat=32
402 state++
403 }
404 else {
405 for (i=1;i<$2;i++) c[$1+i]=$1+i
406 c[$1+$2]=268435455
407 }
408 next
409 }
410 if (state==1) {
411 prev=$1
412 state++
413 next
414 }
415 if (state==2) {
416 if (fat==12) {
417 n=($1%16)*256+prev
418 if (n!=0) c[pos+1]=n
419 pos++
420 prev=int($1/16)
421 state++
422 next
423 }
424 n=$1*256+prev
425 if (fat==32) {
426 prev=n
427 state=13
428 next
429 }
430 }
431 else if (state==3) {
432 n=$1*16+prev
433 }
434 else if (state==13) {
435 prev=$1*65536+prev
436 state++
437 next
438 }
439 else n=$1*16777216+prev
440 if (n!=0) c[pos+1]=n
441 pos++
442 state=1
443 }
444 END {
445 for (i=1;i<=pos;i+=2) {
446 if (c[i]=="") c[i]=0
447 if (c[i+1]=="") c[i+1]=0
448 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
449 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
450 else {
451 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
452 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
453 }
454 }
455 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
456 conv=notrunc bs=512 > /dev/null 2>&1
457 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
458 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
460 # Cleanup cache
461 umount $2
462 mount -o loop,ro $1 $2
463 }
466 # allocate efi.img stub to share EFI files in the EFI boot partition
468 alloc_uefi_part() {
469 local basedir=$(dirname "$1")/..
470 if [ -s $basedir/boot/isolinux/efi.img ]; then
471 chmod +x $basedir/boot/isolinux/efi.img
472 return
473 fi
474 local fclust=$({
475 [ -d $basedir/efi ] &&
476 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
477 while [ -s "$1" ]; do
478 local efifile
479 case "$1" in
480 *taz) efifile=bootia32.efi ;;
481 *taz64) efifile=bootx64.efi ;;
482 esac
483 if [ ! -s $basedir/efi/boot/$efifile ] &&
484 [ $(get $((0x82)) "$1") = $((0x4550)) ]; then
485 mkdir -p $basedir/efi/boot 2> /dev/null
486 ln "$1" "$basedir/efi/boot/$efifile"
487 stat -c "%s %n" "$1"
488 for i in $basedir/boot/rootfs* ; do
489 ln "$i" $basedir/efi/boot/ &&
490 stat -c "%s %n" "$i"
491 done 2> /dev/null
492 [ -s $basedir/efi/boot/linux.cmdline ] ||
493 sed 's|/|\\|g' > $basedir/efi/boot/linux.cmdline <<EOT
494 rw root=0x100 autologin\
495 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
496 echo -n " initrd=/EFI/BOOT/$f";done)
497 EOT
498 fi
499 shift
500 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
501 [ ${fclust:-0} -eq 0 ] && return
502 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
503 BEGIN {
504 FS="/"
505 }
506 NF > 1 {
507 d[NF $NF]+=2
508 d[NF-1 $(NF-1)]+=($NF+25)/13
509 }
510 END {
511 for (i in d)
512 n+=int((d[i]+63)/64)
513 print n
514 }')
515 local clusters=$(($fclust+$dclust))
516 if [ $clusters -lt 4068 ]; then
517 fsect=$(((($clusters+2)*3+1023)/1024))
518 ftype="31 32"
519 fhead="F8 FF FF"
520 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
521 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
522 rootsz=2
523 elif [ $clusters -lt 65525 ]; then
524 fsect=$((($clusters+2+255)/256))
525 ftype="31 36"
526 fhead="F8 FF FF FF"
527 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
528 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
529 rootsz=2
530 else
531 fsect=$((($clusters+2+127)/128))
532 ftype="33 32"
533 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
534 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
535 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
536 rootsz=1
537 fi
538 # reserved + fat*2 + root dir + dirs
539 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
540 s=$((($count+$fclust)*4))
541 if [ $s -gt 65535 ]; then
542 size="00 00"
543 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
544 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
545 else
546 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
547 size32="00 00 00 00"
548 fi
549 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
550 count=$s 2> /dev/null
552 # Create boot sector
553 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
554 if [ "$ftype" = "33 32" ]; then
555 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
556 conv=notrunc
557 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
558 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
559 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
560 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
561 0 80 00 29 00 00 00 00 $doslabel |
562 0 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
563 EOT
564 while read ofs data; do
565 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
566 bs=1 seek=$ofs of=$basedir/boot/isolinux/efi.img
567 done <<EOT
568 510 55:aa:52:52:61:41
569 996 72:72:41:61:ff:ff:ff:ff:02
570 1022 55:aa
571 EOT
572 else
573 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
574 seek=510 bs=1 conv=notrunc
575 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
576 conv=notrunc
577 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
578 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
579 0 $size32 80 00 29 00 00 00 00 $doslabel |
580 0 46 41 54 $ftype 20 20 20 cd 18 |
581 0 cd 19 eb fa |
582 EOT
583 fi 2> /dev/null
585 # Create fats
586 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
587 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
588 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
589 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
591 # Add label
592 echo "0 $doslabel 08 |" | hexdump -R | \
593 dd of=$basedir/boot/isolinux/efi.img bs=512 conv=notrunc \
594 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
596 mkdir -p /tmp/mnt$$
597 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
598 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
599 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
600 sync
601 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
602 skip=$rsect bs=512 count=$fsect 2> /dev/null
603 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
604 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
605 umount /tmp/mnt$$
606 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
607 seek=$rsect bs=512 conv=notrunc 2> /dev/null
608 rm /tmp/fat$$
609 rmdir /tmp/mnt$$
611 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
612 seek=$count 2> /dev/null
613 }
616 # isolinux.conf doesn't know the kernel version.
617 # We name the kernel image 'bzImage'.
618 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
620 make_bzImage_hardlink() {
621 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
622 rm -f ${1:-.}/bzImage 2>/dev/null
623 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
624 fi
625 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
626 rm -f ${1:-.}/bzImage64 2> /dev/null
627 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
628 fi
629 }
632 create_iso() {
633 cd $2
634 deduplicate
636 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
637 make_bzImage_hardlink $2/boot
638 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
640 while read file; do ls -r $file 2> /dev/null; done << EOT | \
641 awk 'BEGIN { n=100 } { print $1 " " n-- }' > /tmp/cdsort$$
642 $PWD/boot/isolinux/boot.cat
643 $PWD/boot/isolinux/isolinux.bin
644 $PWD/boot/isolinux/isolinux.cfg
645 $PWD/boot/isolinux/vesamenu.c32
646 $PWD/boot/isolinux/splash.*g
647 $PWD/boot/isolinux/i18n.cfg
648 $PWD/boot/isolinux/c32box.c32
649 $PWD/boot/isolinux/kbd
650 $PWD/boot/isolinux/efi.img
651 $PWD/boot/bzImage*
652 $PWD/efi/boot/linux.cmdline*
653 $PWD/boot/rootfs*
654 EOT
656 action 'Computing md5...'
657 touch boot/isolinux/boot.cat
658 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
659 sort -k 2 > md5sum
660 status
662 cd - >/dev/null
663 title 'Generating ISO image'
665 _ 'Generating %s' "$1"
666 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
667 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
668 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
669 -no-emul-boot -boot-load-size 4 -boot-info-table \
670 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
671 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
672 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
673 -A "tazlito $VERSION/$(genisoimage --version)" \
674 -copyright README -P "www.slitaz.org" -no-pad $2
675 rm -f /tmp/cdsort$$
676 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
678 mkdir /tmp/mnt$$
679 mount -o loop,ro $1 /tmp/mnt$$
680 fixup_uefi_part $1 /tmp/mnt$$
681 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
682 ${uefi:+boot/isolinux/efi.img} ; do
683 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
684 done
685 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
686 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
687 umount -d /tmp/mnt$$
688 rmdir /tmp/mnt$$
690 if [ -s '/etc/tazlito/info' ]; then
691 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
692 action 'Storing ISO info...'
693 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
694 status
695 fi
696 fi
698 if [ -x '/usr/bin/isohybrid' ]; then
699 action 'Creating hybrid ISO...'
700 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
701 status
702 fi
704 if [ -x '/usr/bin/iso2exe' ]; then
705 echo 'Creating EXE header...'
706 /usr/bin/iso2exe $1 2>/dev/null
707 fi
708 }
711 # Generate a new ISO image using isolinux.
713 gen_livecd_isolinux() {
714 # Some packages may want to alter iso
715 genisohooks iso
716 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
718 # Set date for boot msg.
719 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
720 DATE=$(date +%Y%m%d)
721 action 'Setting build date to: %s...' "$DATE"
722 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
723 status
724 fi
726 cd $DISTRO
727 create_iso $ISO_NAME.iso $ROOTCD
729 action 'Creating the ISO md5sum...'
730 md5sum $ISO_NAME.iso > $ISO_NAME.md5
731 status
733 separator
734 # Some packages may want to alter final iso
735 genisohooks final
736 }
739 lzma_history_bits() {
740 #
741 # This generates an ISO which boots with Qemu but gives
742 # rootfs errors in frugal or liveUSB mode.
743 #
744 # local n
745 # local sz
746 # n=20 # 1Mb
747 # sz=$(du -sk $1 | cut -f1)
748 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
749 # n=$(( $n + 1 ))
750 # sz=$(( $sz / 2 ))
751 # done
752 # echo $n
753 echo ${LZMA_HISTORY_BITS:-24}
754 }
757 lzma_switches() {
758 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
759 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
760 }
763 lzma_set_size() {
764 # Update size field for lzma'd file packed using -si switch
765 return # Need to fix kernel code?
767 local n i
768 n=$(unlzma < $1 | wc -c)
769 for i in $(seq 1 8); do
770 printf '\\\\x%02X' $(($n & 255))
771 n=$(($n >> 8))
772 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
773 }
776 align_to_32bits() {
777 local size=$(stat -c %s ${1:-/dev/null})
778 [ $((${size:-0} & 3)) -ne 0 ] &&
779 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
780 }
783 dolz4() {
784 [ "$(which lz4)" ] || tazpkg get-install lz4
785 lz4 -9 > $1
786 }
789 dogzip() {
790 gzip -9 > $1
791 [ -x /usr/bin/advdef ] && advdef -qz4 $1
792 }
795 # Pack rootfs
797 pack_rootfs() {
798 ( cd $1; find . -print | cpio -o -H newc ) | \
799 case "$COMPRESSION" in
800 none)
801 _ 'Creating %s without compression...' 'initramfs'
802 cat > $2
803 ;;
804 lz4)
805 _ 'Creating %s with lz4 compression...' 'initramfs'
806 dolz4 $2
807 ;;
808 gzip)
809 _ 'Creating %s with gzip compression...' 'initramfs'
810 dogzip $2
811 ;;
812 *)
813 _ 'Creating %s with lzma compression...' 'initramfs'
814 lzma e -si -so $(lzma_switches $1) > $2
815 lzma_set_size $2
816 ;;
817 esac
818 align_to_32bits $2
819 echo 1 > /tmp/rootfs
820 }
823 # Compression functions for writeiso.
825 write_initramfs() {
826 case "$COMPRESSION" in
827 lzma)
828 _n 'Creating %s with lzma compression...' "$INITRAMFS"
829 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
830 align='y'
831 lzma_set_size "/$INITRAMFS"
832 ;;
833 gzip)
834 _ 'Creating %s with gzip compression...' "$INITRAMFS"
835 cpio -o -H newc | dogzip "/$INITRAMFS"
836 ;;
837 lz4)
838 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
839 cpio -o -H newc | dolz4 "/$INITRAMFS"
840 ;;
841 *)
842 # align='y'
843 _ 'Creating %s without compression...' "$INITRAMFS"
844 cpio -o -H newc > "/$INITRAMFS"
845 ;;
846 esac < /tmp/list
847 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
848 echo 1 > /tmp/rootfs
849 }
852 # Deduplicate files (MUST be on the same filesystem).
854 deduplicate() {
855 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
856 (
857 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
858 while read attr inode link file; do
859 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
860 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
861 rm -f "$file"
862 if ln "$old_file" "$file" 2>/dev/null; then
863 hinode="$inode"
864 inode="$old_inode"
865 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
866 save="$(($save+(${attr%%-*}+512)/1024))"
867 continue
868 else
869 cp -p "$old_file" "$file"
870 fi
871 else
872 hinode=""
873 fi
874 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
875 done
876 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
877 )
879 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
880 while read attr inode link file; do
881 echo "$attr-$(readlink "$file" | uuencode -m - | \
882 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
883 done | sort | \
884 (
885 old_attr=""; hardlinks=0;
886 while read attr inode link file; do
887 if [ "$attr" = "$old_attr" ]; then
888 if [ "$inode" != "$old_inode" ]; then
889 rm -f "$file"
890 if ln "$old_file" "$file" 2>/dev/null; then
891 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
892 else
893 cp -a "$old_file" "$file"
894 fi
895 fi
896 else
897 old_file="$file"
898 old_attr="$attr"
899 old_inode="$inode"
900 fi
901 done
902 _ '%s duplicate symlinks.' "$hardlinks"
903 )
904 }
907 # Generate a new initramfs from the root filesystem.
909 gen_initramfs() {
910 # Just in case CTRL+c
911 rm -f $DISTRO/gen
913 # Some packages may want to alter rootfs
914 genisohooks rootfs
915 cd $1
917 # Normalize file time
918 find $1 -newer $1 -exec touch -hr $1 {} \;
920 # Link duplicate files
921 deduplicate
923 # Use lzma if installed. Display rootfs size in realtime.
924 rm -f /tmp/rootfs 2>/dev/null
925 pack_rootfs . $DISTRO/$(basename $1).gz &
926 sleep 2
927 echo -en "\nFilesystem size:"
928 while [ ! -f /tmp/rootfs ]; do
929 sleep 1
930 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
931 done
932 echo -e "\n"
933 rm -f /tmp/rootfs
934 cd $DISTRO
935 mv $(basename $1).gz $ROOTCD/boot
936 }
939 distro_sizes() {
940 if [ -n "$start_time" ]; then
941 time=$(($(date +%s) - $start_time))
942 sec=$time
943 div=$(( ($time + 30) / 60))
944 [ "$div" -ne 0 ] && min="~ ${div}m"
945 _ 'Build time : %ss %s' "$sec" "$min"
946 fi
947 cat <<EOT
948 Build date : $(date +%Y%m%d)
949 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
950 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
951 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
952 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
953 EOT
954 footer "Image is ready: $ISO_NAME.iso"
955 }
958 # Print ISO and rootfs size.
960 distro_stats() {
961 title 'Distro statistics: %s' "$DISTRO"
962 distro_sizes
963 }
966 # Create an empty configuration file.
968 empty_config_file() {
969 cat >> tazlito.conf <<"EOF"
970 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
971 #
973 # Name of the ISO image to generate.
974 ISO_NAME=""
976 # ISO image volume name.
977 VOLUM_NAME="SliTaz"
979 # Name of the preparer.
980 PREPARED="$USER"
982 # Path to the packages repository and the packages.list.
983 PACKAGES_REPOSITORY=""
985 # Path to the distro tree to gen-distro from a list of packages.
986 DISTRO=""
988 # Path to the directory containing additional files
989 # to copy into the rootfs and rootcd of the LiveCD.
990 ADDFILES="$DISTRO/addfiles"
992 # Default answer for binary question (Y or N)
993 DEFAULT_ANSWER="ASK"
995 # Compression utility (lzma, gzip or none)
996 COMPRESSION="lzma"
997 EOF
998 }
1001 # Extract rootfs.gz somewhere
1003 extract_rootfs() {
1004 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
1005 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1006 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1007 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1008 (cd "$2"; cpio -idm --quiet 2>/dev/null < "$1")
1012 # Extract flavor file to temp directory
1014 extract_flavor() {
1015 # Input: $1 - flavor name to extract;
1016 # $2 = absent/empty: just extract 'outer layer'
1017 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1018 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1019 # Output: temp dir path where flavor was extracted
1020 local f="$1.flavor" from to infos="$1.desc"
1021 [ -f "$f" ] || die "File '$f' not found"
1022 local dir="$(mktemp -d)"
1023 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1025 if [ -n "$2" ]; then
1026 cd $dir
1028 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1030 for i in rootcd rootfs; do
1031 [ -f "$1.$i" ] || continue
1032 mkdir "$i"
1033 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1034 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1035 rm "$1.$i"
1036 done
1037 touch -t 197001010100.00 $1.*
1038 # Info to be stored inside ISO
1039 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1040 rm $1.list*
1042 # Renames
1043 while read from to; do
1044 [ -f "$from" ] || continue
1045 mv "$from" "$to"
1046 done <<EOT
1047 $1.nonfree non-free.list
1048 $1.pkglist packages.list
1049 $1-distro.sh distro.sh
1050 $1.receipt receipt
1051 $1.mirrors mirrors
1052 $1.desc description
1053 EOT
1054 fi
1056 echo $dir
1060 # Pack flavor file from temp directory
1062 pack_flavor() {
1063 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1067 # Remove duplicate files
1069 files_match() {
1070 if [ -d "$1" ]; then
1071 return 1
1073 elif [ -L "$1" ] && [ -L "$2" ]; then
1074 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1076 elif [ -f "$1" ] && [ -f "$2" ]; then
1077 cmp -s "$1" "$2" && return 0
1079 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1080 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1081 return 0
1083 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1084 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1085 return 0
1087 fi 2> /dev/null
1088 return 1
1091 remove_with_path() {
1092 dir="$(dirname $1)"
1093 rm -f "$1"
1094 while rmdir "$dir" 2> /dev/null; do
1095 dir="$(dirname $dir)"
1096 done
1099 mergefs() {
1100 # Note, many packages have files with spaces in the name
1101 IFS=$'\n'
1103 local size1=$(du -hs "$1" | awk '{ print $1 }')
1104 local size2=$(du -hs "$2" | awk '{ print $1 }')
1105 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1107 # merge symlinks files and devices
1108 ( cd "$1"; find ) | \
1109 while read file; do
1110 files_match "$1/$file" "$2/$file" "$file" &&
1111 remove_with_path "$2/$file"
1112 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1113 done
1115 unset IFS
1116 status
1120 cleanup_merge() {
1121 rm -rf $TMP_DIR
1122 exit 1
1126 # Update isolinux config files for multiple rootfs
1128 update_bootconfig() {
1129 local files
1130 action 'Updating boot config files...'
1131 files="$(grep -l 'include common' $1/*.cfg)"
1132 for file in $files; do
1133 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1134 if (/label/) label=$0;
1135 else if (/kernel/) kernel=$0;
1136 else if (/append/) {
1137 i=index($0,"rootfs.gz");
1138 append=substr($0,i+9);
1140 else if (/include/) {
1141 for (i = 1; i <= n; i++) {
1142 print label i
1143 print kernel;
1144 initrd="initrd=/boot/rootfs" n ".gz"
1145 for (j = n - 1; j >= i; j--) {
1146 initrd=initrd ",/boot/rootfs" j ".gz";
1148 printf "\tappend %s%s\n",initrd,append;
1149 print "";
1151 print;
1153 else print;
1154 }' < $file > $file.$$
1155 mv -f $file.$$ $file
1156 done
1157 sel="$(echo $2 | awk '{
1158 for (i=1; i<=NF; i++)
1159 if (i % 2 == 0) printf " slitaz%d", i/2
1160 else printf " %s", $i
1161 }')"
1163 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1165 label slitaz
1166 kernel /boot/isolinux/ifmem.c32
1167 append$sel noram
1169 label noram
1170 config noram.cfg
1172 EOT
1174 # Update vesamenu
1175 if [ -s "$1/isolinux.cfg" ]; then
1176 files="$files $1/isolinux.cfg"
1177 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1178 BEGIN {
1179 kernel = " COM32 c32box.c32"
1182 if (/ROWS/) print "MENU ROWS " n+$3;
1183 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1184 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1185 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1186 else if (/VSHIFT/) {
1187 x = $3-n;
1188 if (x < 0) x = 0;
1189 print "MENU VSHIFT " x;
1191 else if (/rootfs.gz/) {
1192 linux = "";
1193 if (/bzImage/) linux = "linux /boot/bzImage ";
1194 i = index($0, "rootfs.gz");
1195 append = substr($0, i+9);
1196 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1197 printf "\tappend%s noram\n", sel;
1198 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1199 for (i = 1; i <= n; i++) {
1200 print "LABEL slitaz" i
1201 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1202 printf "%s\n", kernel;
1203 initrd = "initrd=/boot/rootfs" n ".gz"
1204 for (j = n - 1; j >= i; j--) {
1205 initrd = initrd ",/boot/rootfs" j ".gz";
1207 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1210 else if (/bzImage/) kernel = $0;
1211 else print;
1212 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1213 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1214 fi
1216 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1217 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1218 cat > $1/noram.cfg <<EOT
1219 implicit 0
1220 prompt 1
1221 timeout 80
1222 $(grep '^F[0-9]' $1/isolinux.cfg)
1224 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1225 say Not enough RAM to boot slitaz. Trying hacker mode...
1226 default hacker
1227 label hacker
1228 KERNEL /boot/bzImage
1229 append rw root=/dev/null vga=normal
1231 label reboot
1232 EOT
1234 if [ -s $1/c32box.c32 ]; then
1235 cat >> $1/noram.cfg <<EOT
1236 COM32 c32box.c32
1237 append reboot
1239 label poweroff
1240 COM32 c32box.c32
1241 append poweroff
1243 EOT
1244 else
1245 echo " com32 reboot.c32" >> $1/noram.cfg
1246 fi
1248 # Restore real label names
1249 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1250 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1251 while read pat; do
1252 sed -i "s/slitaz$pat/" $files
1253 done
1254 status
1258 # Uncompress rootfs or module to stdout
1260 uncompress() {
1261 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1262 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1266 # Install a missing package
1268 install_package() {
1269 if [ -z "$2" ]; then
1270 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1271 else
1272 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1273 fi
1274 case "$answer" in
1275 y)
1276 # We don't want package on host cache.
1277 action 'Getting and installing package: %s' "$1"
1278 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1279 status ;;
1280 *)
1281 return 1 ;;
1282 esac
1286 # Check iso for loram transformation
1288 check_iso_for_loram() {
1289 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1290 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1294 # Remove duplicated files in $1/efi/boot from $1/boot
1296 cleanup_efi_boot() {
1297 [ -s $1/boot/isolinux/efi.img ] &&
1298 [ ! -x $1/boot/isolinux/efi.img ] &&
1299 rm -f $1/boot/isolinux/efi.img
1300 for i in $1/efi/boot/* ; do
1301 [ -f $i ] || continue
1302 case "$i" in
1303 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1304 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1305 rm $1/efi/boot/linux.cmdline ;;
1306 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1307 rm $1/efi/boot/linux.cmdline* ;;
1308 esac
1309 rm -f $i
1310 rmdir $1/efi/boot && rmdir $1/efi
1311 done 2> /dev/null
1315 # Build initial rootfs for loram ISO ram/cdrom/http
1317 build_initfs() {
1318 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1319 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1320 mirror3.slitaz.org mirror.slitaz.org"
1321 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1322 [ -z "$version" ] && die "Can't find the kernel version." \
1323 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1325 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1326 need_lib=false
1327 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1328 mkdir -p $TMP_DIR/initfs/$i
1329 done
1330 ln -s bin $TMP_DIR/initfs/sbin
1331 ln -s . $TMP_DIR/initfs/usr
1332 for aufs in aufs overlayfs; do
1333 for v in $version ; do
1334 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1335 install_package ${v/*taz/linux}-$aufs $v && continue
1336 done
1337 install_package $aufs $version && break
1338 done || return 1
1339 [ -s /init ] || install_package slitaz-boot-scripts
1340 cp /init $TMP_DIR/initfs/
1341 for v in $version ; do
1342 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1343 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1344 done
1345 if [ "$1" = 'cdrom' ]; then
1346 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1347 else
1348 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1349 for v in $version ; do
1350 while [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; do
1351 install_package linux-squashfs $v || return 1
1352 done
1353 done
1354 for v in $version ; do
1355 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1356 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1357 done
1358 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1359 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1360 fi
1361 if [ "$1" = 'http' ]; then
1362 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1363 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1364 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1365 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1366 cp -a /dev/fuse $TMP_DIR/initfs/dev
1367 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1368 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1369 else
1370 need_lib=true
1371 fi
1372 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1373 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1374 else
1375 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1376 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1377 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1378 cp -a /lib/librt* $TMP_DIR/initfs/lib
1379 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1380 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1381 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1382 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1383 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1384 need_lib=true
1385 fi
1386 cd $TMP_DIR/fs
1387 echo 'Getting slitaz-release & ethernet modules...'
1388 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1389 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1390 [ -s rootfs* ] || continue
1391 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1392 rm -f rootfs*
1393 done 2>&1 > /dev/null
1394 cd - > /dev/null
1395 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1396 for v in $version ; do
1397 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1398 -type f -name '*.ko*' | while read mod; do
1399 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1400 uncompress $mod > $f
1401 grep -q alias=pci: $f || rm -f $f
1402 done
1403 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1404 f=$(basename $i)..z
1405 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1406 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1407 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1408 for j in $deps; do
1409 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1410 uncompress $mod > $(echo $j | sed s/..z$//)
1411 done
1412 done
1413 done
1414 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"
1415 _n 'List of URLs to insert: '
1416 read -t 30 urliso2
1417 urliso="$urliso2 $urliso"
1418 fi
1419 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1420 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1421 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1422 else
1423 cp /bin/busybox $TMP_DIR/initfs/bin
1424 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1425 cp /sbin/insmod $TMP_DIR/initfs/bin
1426 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1427 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1428 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1429 fi
1430 need_lib=true
1431 fi
1432 bins="sh switch_root"
1433 [ "$(echo ls | chroot $TMP_DIR/initfs busybox sh 2> /dev/null)" ] ||
1434 bins="$($TMP_DIR/initfs/bin/busybox | awk \
1435 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g')"
1436 for i in $bins ; do
1437 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1438 done
1439 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1440 for v in $version ; do
1441 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1442 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1443 done
1444 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1445 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1446 cp -a $i $TMP_DIR/initfs/dev
1447 done
1448 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1449 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1450 cp -a $i $TMP_DIR/initfs/dev
1451 done 2>/dev/null
1452 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1453 cp -a $i $TMP_DIR/initfs/lib
1454 done
1455 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1456 #!/bin/sh
1458 getarg() {
1459 grep -q " \$1=" /proc/cmdline || return 1
1460 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1461 return 0
1464 copy_rootfs() {
1465 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1466 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1467 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1468 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1469 path=/mnt/
1470 return 0
1471 else
1472 rm -f /mnt/rootfs*
1473 return 1
1474 fi
1477 echo "Switching / to tmpfs..."
1478 mount -t proc proc /proc
1479 size="\$(grep rootfssize= < /proc/cmdline | \\
1480 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1481 [ -n "\$size" ] || size="-o size=90%"
1483 mount -t sysfs sysfs /sys
1484 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1485 [ -s \$i ] && continue
1486 echo -en "Probe \$i \\r"
1487 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1488 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1489 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1490 insmod /lib/modules/\$k.ko 2> /dev/null
1491 done
1492 echo "Loading \$i"
1493 insmod \$i 2> /dev/null
1494 break
1495 done
1496 done
1497 umount /sys
1498 while read var default; do
1499 eval \$var=\$default
1500 getarg \$var \$var
1501 done <<EOT
1502 eth eth0
1503 dns 208.67.222.222,208.67.220.220
1504 netmask 255.255.255.0
1505 gw
1506 ip
1507 EOT
1508 grep -q \$eth /proc/net/dev || sh
1509 if [ -n "\$ip" ]; then
1510 ifconfig \$eth \$ip netmask \$netmask up
1511 route add default gateway \$gw
1512 for i in \$(echo \$dns | sed 's/,/ /g'); do
1513 echo "nameserver \$i" >> /etc/resolv.conf
1514 done
1515 else
1516 udhcpc -f -q -s /lib/udhcpc -i \$eth
1517 fi
1518 for i in $urliso ; do
1519 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1520 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"
1521 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1522 done
1523 getarg urliso URLISO
1524 DIR=fs
1525 if getarg loram DIR; then
1526 DEVICE=\${DIR%,*}
1527 DIR=/\${DIR#*,}
1528 fi
1529 mount -t tmpfs \$size tmpfs /mnt
1530 path2=/mnt/.httpfs/
1531 path=/mnt/.cdrom/
1532 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1533 while [ ! -d \$path/boot ]; do
1534 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1535 httpfs \$i \$path2 && echo \$i && break
1536 done
1537 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1538 done
1540 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1541 umount /proc
1542 branch=:/mnt/.cdrom/\$DIR
1543 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1544 branch=
1545 lp=1
1546 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1547 [ -s \$i ] && insmod \$i
1548 done 2> /dev/null
1549 for i in \${path}boot/rootfs?.* ; do
1550 fs=\${i#*root}
1551 branch=\$branch:/mnt/.\$fs
1552 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1553 losetup -o 124 /dev/loop\$lp \$i
1554 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1555 lp=\$((\$lp+1))
1556 done
1557 fi
1558 mkdir -p /mnt/.rw/mnt/.httpfs
1559 while read type opt; do
1560 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1561 [ -s \$i ] && insmod \$i &&
1562 mount -t \$type -o \$opt none /mnt && break 2
1563 done
1564 done <<EOT
1565 aufs br=/mnt/.rw\$branch
1566 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1567 EOT
1568 rm -rf /lib/modules
1569 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1570 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1571 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1572 EOTEOT
1573 chmod +x $TMP_DIR/initfs/init
1574 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1575 [ -s $i ] || continue
1576 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1577 rm -f $i
1578 done 2>/dev/null
1579 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1580 lzma e $TMP_DIR/initfs.gz -si
1581 lzma_set_size $TMP_DIR/initfs.gz
1582 rm -rf $TMP_DIR/initfs
1583 align_to_32bits $TMP_DIR/initfs.gz
1584 return 0
1588 # Move each initramfs to squashfs
1590 build_loram_rootfs() {
1591 rootfs_sizes=""
1592 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1593 mkdir -p $TMP_DIR/fs
1594 cd $TMP_DIR/fs
1595 uncompress $i | cpio -idm
1596 deduplicate
1597 cd - > /dev/null
1598 rootfs=$TMP_DIR/$(basename $i 64)
1599 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1600 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1601 cd $TMP_DIR
1602 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1603 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1604 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1605 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1606 rm -f $rootfs
1607 mv ${rootfs%64}.cpio $rootfs
1608 cd - > /dev/null
1609 rm -rf $TMP_DIR/fs
1610 done
1614 # Move meta boot configuration files to basic configuration files
1615 # because meta loram flavor is useless when rootfs is not loaded in RAM
1617 unmeta_boot() {
1618 local root=${1:-$TMP_DIR/loramiso}
1619 if [ -f $root/boot/isolinux/noram.cfg ]; then
1620 # We keep enough information to do unloram...
1621 [ -s $root/boot/isolinux/common.cfg ] &&
1622 sed -i 's/label slitaz/label orgslitaz/' \
1623 $root/boot/isolinux/common.cfg
1624 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1625 shift
1626 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1627 $root/boot/isolinux/isolinux.cfg
1628 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1629 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1630 $root/boot/isolinux/*.cfg
1631 fi
1635 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1636 # These squashfs may be loaded in RAM at boot time.
1637 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1638 # Meta flavors are converted to normal flavors.
1640 build_loram_cdrom() {
1641 build_initfs cdrom || return 1
1642 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1643 cleanup_efi_boot $TMP_DIR/loramiso
1644 mkdir $TMP_DIR/loramiso/fs
1645 cd $TMP_DIR/loramiso/fs
1646 for i in $( ls ../boot/root* | sort -r ) ; do
1647 uncompress $i | cpio -idmu
1648 rm -f $i
1649 done
1650 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1651 cd - >/dev/null
1652 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1653 unmeta_boot
1654 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1655 busybox sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1656 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1657 busybox sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' \
1658 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1659 create_iso $OUTPUT $TMP_DIR/loramiso
1663 # Create http bootstrap to load and remove loram_cdrom
1664 # Meta flavors are converted to normal flavors.
1666 build_loram_http() {
1667 build_initfs http || return 1
1668 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1669 cleanup_efi_boot $TMP_DIR/loramiso
1670 rm -f $TMP_DIR/loramiso/boot/rootfs*
1671 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1672 unmeta_boot
1673 create_iso $OUTPUT $TMP_DIR/loramiso
1677 # Update meta flavor selection sizes.
1678 # Reduce sizes with rootfs gains.
1680 update_metaiso_sizes() {
1681 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1682 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1683 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1684 do
1685 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1686 local sizes="$rootfs_sizes"
1687 local new
1688 set -- $append
1689 shift
1690 [ "$1" = "ifmem" ] && shift
1691 new=""
1692 while [ -n "$2" ]; do
1693 local s
1694 case "$1" in
1695 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1696 *M) s=$(( ${1%M} * 1024 ));;
1697 *) s=${1%K};;
1698 esac
1699 sizes=${sizes#* }
1700 for i in $sizes ; do
1701 s=$(( $s - $i ))
1702 done
1703 new="$new $s $2"
1704 shift 2
1705 done
1706 busybox sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1707 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1708 busybox sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1709 busybox sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1710 busybox sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' $cfg
1711 done
1715 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1716 # Meta flavor selection sizes are updated.
1718 build_loram_ram() {
1719 build_initfs ram || return 1
1720 build_loram_rootfs "$1"
1721 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1722 cleanup_efi_boot $TMP_DIR/loramiso
1723 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1724 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1725 update_metaiso_sizes
1726 create_iso $OUTPUT $TMP_DIR/loramiso
1730 # Remove files installed by packages
1732 find_flavor_rootfs() {
1733 for i in $1/etc/tazlito/*.extract; do
1734 [ -e $i ] || continue
1735 chroot $1 /bin/sh ${i#$1}
1736 done
1738 # Clean hardlinks and files patched by genisofs in /boot
1739 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1740 rm -f $1/boot/$i*
1741 done
1743 # Clean files generated in post_install
1744 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1745 $1/dev/core $1/dev/fd $1/dev/std*
1747 # Verify md5
1748 cat $1$INSTALLED/*/md5sum | \
1749 while read md5 file; do
1750 [ -e "$1$file" ] || continue
1751 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1752 rm -f "$1$file"
1753 done
1755 # Check configuration files
1756 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1757 [ -e $i ] || continue
1758 mkdir /tmp/volatile$$
1759 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1760 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1761 while read file ; do
1762 [ -e "$1/$file" ] || continue
1763 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1764 done
1765 rm -rf /tmp/volatile$$
1766 done
1768 # Remove other files blindly
1769 for i in $1$INSTALLED/*/files.list; do
1770 while read file; do
1771 [ "$1$file" -nt "$i" ] && continue
1772 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1773 [ -d "$1$file" ] || rm -f "$1$file"
1774 done < $i
1775 done
1777 # Remove tazpkg files and tmp files
1778 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1779 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1780 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1781 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1782 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1784 # Cleanup directory tree
1785 cd $1
1786 find * -type d | sort -r | while read dir; do
1787 rmdir "$dir" 2>/dev/null
1788 done
1789 cd - > /dev/null
1793 # Get byte(s) from a binary file
1795 get() {
1796 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1800 # Get cpio flavor info from the ISO image
1802 flavordata() {
1803 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1804 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1808 # Restore undigest mirrors
1810 restore_mirrors() {
1811 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1812 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1814 action 'Restoring mirrors...'
1815 if [ -d "$undigest.bak" ]; then
1816 [ -d "$undigest" ] && rm -r "$undigest"
1817 mv "$undigest.bak" "$undigest"
1818 fi
1819 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1820 :; status
1824 # Setup undigest mirrors
1826 setup_mirrors() {
1827 # Setup mirrors in plain system or in chroot (with variable root=)
1828 local mirrorlist="$1" fresh repacked
1829 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1831 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1832 restore_mirrors
1834 _ 'Setting up mirrors for %s...' "$root/"
1835 # Backing up current undigest mirrors and priority
1836 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1837 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1838 rm -rf '/var/www/tazlito/'
1839 mkdir -p '/var/www/tazlito/'
1841 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1842 fresh='/home/slitaz/packages'
1843 if [ -d "$fresh" ]; then
1844 # Setup first undigest mirror
1845 mkdir -p "$undigest/fresh"
1846 echo "$fresh" > "$undigest/fresh/mirror"
1847 echo 'fresh' >> "$priority"
1848 # Rebuild mirror DB if needed
1849 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1850 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1851 tazpkg mkdb "$fresh" --forced --root=''
1852 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1853 fi
1855 # Repacked packages: high priority
1856 repacked="$PACKAGES_REPOSITORY"
1857 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1858 # According to Tazlito setup file (tazlito.conf):
1859 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1860 # or
1861 # WORK_DIR="/home/slitaz"
1862 # and
1863 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1864 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1866 # Setup second undigest mirror
1867 mkdir -p "$undigest/repacked"
1868 echo "$repacked" > "$undigest/repacked/mirror"
1869 echo 'repacked' >> "$priority"
1870 # Rebuild mirror DB if needed
1871 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1872 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1873 tazpkg mkdb "$repacked" --forced --root=''
1874 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1875 fi
1877 # All repositories listed in mirrors list: normal priority
1878 [ -e "$mirrorlist" ] && \
1879 while read mirror; do
1880 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1881 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1882 mkdir -p "$undigest/$mirrorid"
1883 echo "$mirror" > "$undigest/$mirrorid/mirror"
1884 echo "$mirrorid" >> "$priority"
1885 done < "$mirrorlist"
1887 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1889 # Show list of mirrors
1890 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1891 function show(num, name, url) {
1892 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1895 num++;
1896 "cat " db "/undigest/" $0 "/mirror" | getline url;
1897 show(num, $0, url);
1899 END {
1900 num++;
1901 "cat " db "/mirror" | getline url;
1902 show(num, "main", url);
1903 }' "$priority"
1905 tazpkg recharge --quiet >/dev/null
1909 # Get list of 'packages.info' lists using priority
1911 pi_lists() {
1912 local pi
1913 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1914 local priority="$root$LOCALSTATE/priority"
1915 local undigest="$root$LOCALSTATE/undigest"
1918 [ -s "$priority" ] && cat "$priority"
1919 echo 'main'
1920 [ -d "$undigest" ] && ls "$undigest"
1921 } | awk -vun="$undigest/" '
1923 if (arr[$0] != 1) {
1924 arr[$0] = 1;
1925 print un $0 "/packages.info";
1927 }' | sed 's|/undigest/main||' | \
1928 while read pi; do
1929 [ -e "$pi" ] && echo "$pi"
1930 done
1934 # Strip versions from packages list
1936 strip_versions() {
1937 if [ -n "$stripped" ]; then
1938 action 'Consider list %s already stripped' "$(basename "$1")"
1939 status
1940 return 0
1941 fi
1942 action 'Strip versions from list %s...' "$(basename "$1")"
1943 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1944 [ -f "$in_list" ] || die "List '$in_list' not found."
1946 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1947 awk '
1949 if (FILENAME ~ "packages.info") {
1950 # Collect package names
1951 FS = "\t"; pkg[$1] = 1;
1952 } else {
1953 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1954 while (NF > 1 && ! pkg[$0])
1955 NF --;
1956 printf "%s\n", $0;
1958 }' $(pi_lists) "$in_list" > "$tmp_list"
1960 cat "$tmp_list" > "$in_list"
1961 rm "$tmp_list"
1962 status
1966 # Display list of unknown packages (informative)
1968 display_unknown() {
1969 [ -s "$1" ] || return
1970 echo "Unknown packages:" >&2
1971 cat "$1" >&2
1972 rm "$1"
1976 # Display warnings about critical packages absent (informative)
1978 display_warn() {
1979 [ -s "$1" ] || return
1980 echo "Absent critical packages:" >&2
1981 cat "$1" >&2
1982 rm "$1"
1983 echo "Probably ISO image will be unusable."
1987 # Install packages to rootfs
1989 install_list_to_rootfs() {
1990 local list="$1" rootfs="$2" pkg i ii
1991 local undigest="$rootfs/var/lib/tazpkg/undigest"
1993 # initial tazpkg setup in empty rootfs
1994 tazpkg --root=$rootfs >/dev/null 2>&1
1995 # pass current 'mirror' to the rootfs
1996 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1997 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1998 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1999 # link rootfs packages cache to the regular packages cache
2000 rm -r "$rootfs/var/cache/tazpkg"
2001 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
2003 setup_mirrors mirrors
2005 # Just in case if flavor doesn't contain "tazlito" package
2006 mkdir -p "$rootfs/etc/tazlito"
2008 newline
2010 # Choose detailed log with --detailed
2011 if [ -n "$detailed" ]; then
2012 while read pkg; do
2013 separator '-'
2014 echo $pkg
2015 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2016 done < $list
2017 separator '='
2018 else
2019 while read pkg; do
2020 action 'Installing package: %s' "$pkg"
2021 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2022 status
2023 done < $list
2024 fi
2025 newline
2027 restore_mirrors
2028 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2029 for i in fresh repacked; do
2030 ii="$undigest/$i"
2031 [ -d "$ii" ] && rm -rf "$ii"
2032 ii="$rootfs/var/lib/tazpkg/priority"
2033 if [ -f "$ii" ]; then
2034 sed -i "/$i/d" "$ii"
2035 [ -s "$ii" ] || rm "$ii"
2036 fi
2037 done
2038 [ -d "$undigest" ] && \
2039 for i in $(find "$undigest" -type f); do
2040 # Remove all undigest PKGDB files but 'mirror'
2041 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2042 done
2043 [ -d "$undigest" ] && \
2044 rmdir --ignore-fail-on-non-empty "$undigest"
2046 # Un-link packages cache
2047 rm "$rootfs/var/cache/tazpkg"
2049 # Clean /var/lib/tazpkg
2050 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2056 ####################
2057 # Tazlito commands #
2058 ####################
2060 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2061 case "$0" in
2062 *reduplicate)
2063 find ${@:-.} ! -type d -links +1 \
2064 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2065 exit 0 ;;
2066 *deduplicate)
2067 deduplicate "$@"
2068 exit 0 ;;
2069 esac
2072 case "$COMMAND" in
2073 stats)
2074 # Tazlito general statistics from the config file.
2076 title 'Tazlito statistics'
2077 optlist "\
2078 Config file : $CONFIG_FILE
2079 ISO name : $ISO_NAME.iso
2080 Volume name : $VOLUM_NAME
2081 Prepared : $PREPARED
2082 Packages repository : $PACKAGES_REPOSITORY
2083 Distro directory : $DISTRO
2084 Additional files : $ADDFILES
2085 " | sed '/: $/d'
2086 footer
2087 ;;
2090 list-addfiles)
2091 # Simple list of additional files in the rootfs
2092 newline
2093 if [ -d "$ADDFILES/rootfs" ]; then
2094 cd $ADDFILES
2095 find rootfs -type f
2096 else
2097 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2098 fi
2099 newline
2100 ;;
2103 gen-config)
2104 # Generate a new config file in the current dir or the specified
2105 # directory by $2.
2107 if [ -n "$2" ]; then
2108 mkdir -p "$2" && cd "$2"
2109 fi
2111 newline
2112 action 'Generating empty tazlito.conf...'
2113 empty_config_file
2114 status
2116 separator
2117 if [ -f 'tazlito.conf' ] ; then
2118 _ 'Configuration file is ready to edit.'
2119 _ 'File location: %s' "$(pwd)/tazlito.conf"
2120 newline
2121 fi
2122 ;;
2125 configure)
2126 # Configure a tazlito.conf config file. Start by getting
2127 # a empty config file and sed it.
2129 if [ -f 'tazlito.conf' ]; then
2130 rm tazlito.conf
2131 else
2132 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2133 'or in the same directory of the file you want to configure.'
2134 cd /etc
2135 fi
2137 empty_config_file
2139 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2141 # ISO name.
2142 echo -n "ISO name : " ; read answer
2143 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2144 # Volume name.
2145 echo -n "Volume name : " ; read answer
2146 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2147 # Packages repository.
2148 echo -n "Packages repository : " ; read answer
2149 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2150 # Distro path.
2151 echo -n "Distro path : " ; read answer
2152 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2153 footer "Config file is ready to use."
2154 echo 'You can now extract an ISO or generate a distro.'
2155 newline
2156 ;;
2159 gen-iso)
2160 # Simply generate a new iso.
2162 check_root
2163 verify_rootcd
2164 gen_livecd_isolinux
2165 distro_stats
2166 ;;
2169 gen-initiso)
2170 # Simply generate a new initramfs with a new iso.
2172 check_root
2173 verify_rootcd
2174 gen_initramfs "$ROOTFS"
2175 gen_livecd_isolinux
2176 distro_stats
2177 ;;
2180 extract-distro|extract-iso)
2181 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2183 check_root
2184 ISO_IMAGE="$2"
2185 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2186 'Example:\n tazlito image.iso /path/target'
2188 # Set the distro path by checking for $3 on cmdline.
2189 TARGET="${3:-$DISTRO}"
2191 # Exit if existing distro is found.
2192 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2193 'Please clean the distro tree or change directory path.'
2195 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2197 # Start to mount the ISO.
2198 action 'Mounting ISO image...'
2199 mkdir -p "$TMP_DIR"
2200 # Get ISO file size.
2201 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2202 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2203 sleep 2
2204 # Prepare target dir, copy the kernel and the rootfs.
2205 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2206 status
2208 action 'Copying the Linux kernel...'
2209 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2210 make_bzImage_hardlink "$TARGET/rootcd/boot"
2211 else
2212 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2213 fi
2214 status
2216 for i in $(ls $TMP_DIR); do
2217 [ "$i" = 'boot' ] && continue
2218 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2219 done
2221 for loader in isolinux syslinux extlinux grub; do
2222 [ -d "$TMP_DIR/boot/$loader" ] || continue
2223 action 'Copying %s files...' "$loader"
2224 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2225 status
2226 done
2228 action 'Copying the rootfs...'
2229 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2230 status
2232 cleanup_efi_boot "$TARGET/rootcd"
2234 # Extract initramfs.
2235 cd "$TARGET/rootfs"
2236 action 'Extracting the rootfs...'
2237 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2238 extract_rootfs "$i" "$TARGET/rootfs"
2239 done
2240 # unpack /usr
2241 for i in etc/tazlito/*.extract; do
2242 [ -f "$i" ] && . $i ../rootcd
2243 done
2244 # Umount and remove temp directory and cd to $TARGET to get stats.
2245 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2246 cd ..
2247 status
2249 newline
2250 separator
2251 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2252 echo "Distro tree : $(pwd)"
2253 echo "Rootfs size : $(du -sh rootfs)"
2254 echo "Rootcd size : $(du -sh rootcd)"
2255 footer
2256 ;;
2259 list-flavors)
2260 # Show available flavors.
2261 list='/etc/tazlito/flavors.list'
2262 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2263 title 'List of flavors'
2264 cat $list
2265 footer
2266 ;;
2269 show-flavor)
2270 # Show flavor descriptions.
2271 set -e
2272 flavor=${2%.flavor}
2273 flv_dir="$(extract_flavor "$flavor")"
2274 desc="$flv_dir/$flavor.desc"
2275 if [ -n "$brief" ]; then
2276 if [ -z "$noheader" ]; then
2277 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2278 separator
2279 fi
2280 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2281 "$(field ISO "$desc")" \
2282 "$(field Rootfs "$desc")" \
2283 "$(field Description "$desc")"
2284 else
2285 separator
2286 cat "$desc"
2287 fi
2288 cleanup
2289 ;;
2292 gen-liveflavor)
2293 # Generate a new flavor from the live system.
2294 FLAVOR=${2%.flavor}
2295 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2297 case "$FLAVOR" in
2298 -?|-h*|--help)
2299 cat <<EOT
2300 SliTaz Live Tool - Version: $VERSION
2302 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2304 $(boldify '<flavor-patch-file> format:')
2305 $(optlist "\
2306 code data
2307 + package to add
2308 - package to remove
2309 ! non-free package to add
2310 ? display message
2311 @ flavor description
2312 ")
2314 $(boldify 'Example:')
2315 $(optlist "\
2316 @ Developer tools for SliTaz maintainers
2317 + slitaz-toolchain
2318 + mercurial
2319 ")
2320 EOT
2321 exit 1
2322 ;;
2323 esac
2324 mv /etc/tazlito/distro-packages.list \
2325 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2326 rm -f distro-packages.list non-free.list 2>/dev/null
2327 tazpkg recharge
2329 DESC=""
2330 [ -n "$3" ] && \
2331 while read action pkg; do
2332 case "$action" in
2333 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2334 -) yes | tazpkg remove $pkg ;;
2335 !) echo $pkg >> non-free.list ;;
2336 @) DESC="$pkg" ;;
2337 \?) echo -en "$pkg"; read action ;;
2338 esac
2339 done < $3
2341 yes '' | tazlito gen-distro
2342 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2343 mv /etc/tazlito/distro-packages.list.$$ \
2344 /etc/tazlito/distro-packages.list 2>/dev/null
2345 ;;
2348 gen-flavor)
2349 # Generate a new flavor from the last ISO image generated
2350 FLAVOR=${2%.flavor}
2351 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2353 title 'Flavor generation'
2354 check_rootfs
2355 FILES="$FLAVOR.pkglist"
2357 action 'Creating file %s...' "$FLAVOR.flavor"
2358 for i in rootcd rootfs; do
2359 if [ -d "$ADDFILES/$i" ] ; then
2360 FILES="$FILES\n$FLAVOR.$i"
2361 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2362 fi
2363 done
2364 status
2366 answer=$(grep -s ^Description $FLAVOR.desc)
2367 answer=${answer#Description : }
2368 if [ -z "$answer" ]; then
2369 echo -n "Description: "
2370 read answer
2371 fi
2373 action 'Compressing flavor %s...' "$FLAVOR"
2374 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2375 echo "Description : $answer" >> $FLAVOR.desc
2376 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2377 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2378 for i in $(ls $ROOTFS$INSTALLED); do
2379 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2380 EXTRAVERSION=""
2381 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2382 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2383 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2384 echo "$i" >> $FLAVOR.nonfree
2385 else
2386 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2387 fi
2388 done
2389 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2390 for i in $LOCALSTATE/undigest/*/mirror ; do
2391 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2392 done
2393 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2394 touch -t 197001010100.00 $FLAVOR.*
2395 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2396 rm $(echo -e $FILES)
2397 status
2399 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2400 ;;
2403 upgrade-flavor)
2404 # Strip versions from pkglist and update estimated numbers in flavor.desc
2405 flavor="${2%.flavor}"
2406 set -e
2407 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2408 set +e
2410 flv_dir="$(extract_flavor "$flavor")"
2412 strip_versions "$flv_dir/$flavor.pkglist"
2414 action 'Updating %s...' "$flavor.desc"
2416 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2417 set -- $(module calc_sizes "$flv_dir" "$flavor")
2418 restore_mirrors >/dev/null
2420 sed -i -e '/Image is ready/d' \
2421 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2422 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2423 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2424 -e "s|\(Packages *:\).*$|\1 $4|" \
2425 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2426 "$flv_dir/$flavor.desc"
2428 pack_flavor "$flv_dir" "$flavor"
2429 status
2430 display_unknown "$flv_dir/err"
2431 display_warn "$flv_dir/warn"
2432 cleanup
2433 ;;
2436 extract-flavor)
2437 # Extract a flavor into $FLAVORS_REPOSITORY
2438 flavor="${2%.flavor}"
2439 set -e
2440 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2441 set +e
2443 action 'Extracting %s...' "$flavor.flavor"
2444 flv_dir="$(extract_flavor "$flavor" full)"
2445 storage="$FLAVORS_REPOSITORY/$flavor"
2447 rm -rf "$storage" 2>/dev/null
2448 mkdir -p "$storage"
2449 cp -a "$flv_dir"/* "$storage"
2450 rm "$storage/description"
2451 status
2453 strip_versions "$storage/packages.list"
2455 cleanup
2456 ;;
2459 pack-flavor)
2460 # Create a flavor from $FLAVORS_REPOSITORY.
2461 flavor=${2%.flavor}
2462 storage="$FLAVORS_REPOSITORY/$flavor"
2464 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2466 action 'Creating flavor %s...' "$flavor"
2467 tmp_dir="$(mktemp -d)"
2469 while read from to; do
2470 [ -s "$storage/$from" ] || continue
2471 cp -a "$storage/$from" "$tmp_dir/$to"
2472 done <<EOT
2473 mirrors $flavor.mirrors
2474 distro.sh $flavor-distro.sh
2475 receipt $flavor.receipt
2476 non-free.list $flavor.nonfree
2477 EOT
2479 # Build the package list.
2480 # It can include a list from another flavor with the keyword @include
2481 if [ -s "$storage/packages.list" ]; then
2482 include=$(grep '^@include' "$storage/packages.list")
2483 if [ -n "$include" ]; then
2484 include=${include#@include }
2485 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2486 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2487 else
2488 echo -e "\nERROR: Can't find include package list from $include\n"
2489 fi
2490 fi
2491 # Generate the final/initial package list
2492 [ -s "$storage/packages.list" ] && \
2493 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2494 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2495 fi
2497 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2498 # Process multi-rootfs flavor
2499 . "$storage/receipt"
2500 set -- $ROOTFS_SELECTION
2501 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2502 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2503 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2505 for i in rootcd rootfs; do
2506 mkdir "$tmp_dir/$i"
2507 # Copy extra files from the first flavor
2508 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2509 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2510 # Overload extra files by meta flavor
2511 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2512 [ -n "$(ls $tmp_dir/$i)" ] &&
2513 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2514 dogzip "$tmp_dir/$flavor.$i"
2515 rm -rf "$tmp_dir/$i"
2516 done
2517 else
2518 # Process plain flavor
2519 for i in rootcd rootfs; do
2520 [ -d "$storage/$i" ] || continue
2521 (cd "$storage/$i";
2522 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2523 done
2524 fi
2526 unset VERSION MAINTAINER ROOTFS_SELECTION
2527 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2528 ROOTFS_SIZE="$1 (estimated)"
2529 INITRAMFS_SIZE="$2 (estimated)"
2530 ISO_SIZE="$3 (estimated)"
2531 PKGNUM="$4"
2532 . "$storage/receipt"
2534 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2535 Flavor : $FLAVOR
2536 Description : $SHORT_DESC
2537 Version : $VERSION
2538 Maintainer : $MAINTAINER
2539 LiveCD RAM size : $FRUGAL_RAM
2540 Rootfs list : $ROOTFS_SELECTION
2541 Build date : $(date '+%Y%m%d at %T')
2542 Packages : $PKGNUM
2543 Rootfs size : $ROOTFS_SIZE
2544 Initramfs size : $INITRAMFS_SIZE
2545 ISO image size : $ISO_SIZE
2546 ================================================================================
2548 EOT
2550 rm -f $tmp_dir/packages.list
2551 pack_flavor "$tmp_dir" "$flavor"
2552 status
2553 display_unknown "$tmp_dir/err"
2554 display_warn "$flv_dir/warn"
2555 cleanup
2556 ;;
2559 get-flavor)
2560 # Get a flavor's files and prepare for gen-distro.
2561 flavor=${2%.flavor}
2562 title 'Preparing %s distro flavor' "$flavor"
2563 set -e
2564 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2565 set +e
2567 action 'Cleaning %s...' "$DISTRO"
2568 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2569 # Clean old files
2570 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2571 [ -f "$i" ] && rm "$i"
2572 done
2573 mkdir -p "$DISTRO"
2574 status
2576 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2578 action 'Extracting flavor %s...' "$flavor.flavor"
2579 flv_dir="$(extract_flavor "$flavor" info)"
2580 cp -a "$flv_dir"/* .
2581 mv packages.list distro-packages.list
2582 mv -f info /etc/tazlito
2583 status
2585 for i in rootcd rootfs; do
2586 if [ -d "$i" ]; then
2587 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2588 fi
2589 done
2591 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2592 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2594 action 'Updating %s...' 'tazlito.conf'
2595 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2596 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2597 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2598 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2599 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2600 status
2602 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2603 cleanup
2604 ;;
2607 iso2flavor)
2608 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2609 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2611 FLAVOR=${3%.flavor}
2612 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2613 mount -o loop,ro $2 $TMP_DIR/iso
2614 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2615 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2616 ! -s $TMP_DIR/flavor/*.desc ]; then
2617 _ 'META flavors are not supported.'
2618 umount -d $TMP_DIR/iso
2619 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2620 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2621 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2622 umount -d $TMP_DIR/iso
2623 else
2624 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2625 uncompress $i | \
2626 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2627 done
2628 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2629 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2630 '/etc/slitaz-release' '/boot/rootfs.gz'
2631 umount -d $TMP_DIR/iso
2632 else
2633 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2634 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2635 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2636 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2637 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2638 umount -d $TMP_DIR/iso
2639 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2640 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2641 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2642 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2643 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2644 < $TMP_DIR/rootfs$INSTALLED.md5
2645 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2646 if [ -s $TMP_DIR/flavor/*desc ]; then
2647 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2648 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2649 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2650 for i in rootfs rootcd ; do
2651 [ -s $TMP_DIR/flavor/*.list$i ] &&
2652 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2653 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2654 done
2655 else
2656 find_flavor_rootfs $TMP_DIR/rootfs
2657 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2658 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2659 for i in rootfs rootcd ; do
2660 [ "$(ls $TMP_DIR/$i)" ] &&
2661 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2662 done
2663 unset VERSION MAINTAINER
2664 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2665 if [ -n "$DESCRIPTION" ]; then
2666 _n 'Flavor version : '; read -t 30 VERSION
2667 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2668 fi
2670 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2671 Flavor : $FLAVOR
2672 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2673 Version : ${VERSION:-1.0}
2674 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2675 LiveCD RAM size : $RAM_SIZE
2676 Build date : $BUILD_DATE
2677 Packages : $PKGCNT
2678 Rootfs size : $ROOTFS_SIZE
2679 Initramfs size : $INITRAMFS_SIZE
2680 ISO image size : $ISO_SIZE
2681 ================================================================================
2683 EOT
2684 longline "Tazlito can't detect each file installed during \
2685 a package post_install. You should extract this flavor (tazlito extract-flavor \
2686 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2687 tree and remove files generated by post_installs.
2688 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2689 repack the flavor (tazlito pack-flavor $FLAVOR)"
2690 fi
2691 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2692 fi
2693 fi
2694 rm -rf $TMP_DIR
2695 ;;
2698 gen-distro)
2699 # Generate a live distro tree with a set of packages.
2701 check_root
2702 start_time=$(date +%s)
2704 # Tazlito options: --iso or --cdrom
2705 CDROM=''
2706 [ -n "$iso" ] && CDROM="-o loop $iso"
2707 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2709 # Check if a package list was specified on cmdline.
2710 if [ -f "$2" ]; then
2711 LIST_NAME="$2"
2712 else
2713 LIST_NAME='distro-packages.list'
2714 fi
2716 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2717 'Please clean the distro tree or change directory path.'
2718 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2719 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2721 # If list not given: build list with all installed packages
2722 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2723 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2724 fi
2726 # Exit if no list name.
2727 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2729 # Start generation.
2730 title 'Tazlito generating a distro'
2732 # Misc checks
2733 mkdir -p "$PACKAGES_REPOSITORY"
2734 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2735 newline
2737 # Mount CD-ROM to be able to repack boot-loader packages
2738 if [ ! -e /boot -a -n "$CDROM" ]; then
2739 mkdir $TMP_MNT
2740 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2741 ln -s "$TMP_MNT/boot" /
2742 if [ ! -d "$ADDFILES/rootcd" ] ; then
2743 mkdir -p "$ADDFILES/rootcd"
2744 for i in $(ls $TMP_MNT); do
2745 [ "$i" = 'boot' ] && continue
2746 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2747 done
2748 fi
2749 else
2750 rmdir "$TMP_MNT"
2751 fi
2752 fi
2754 # Rootfs stuff.
2755 echo 'Preparing the rootfs directory...'
2756 mkdir -p "$ROOTFS"
2757 export root="$ROOTFS"
2758 # pass current 'mirror' to the root
2759 mkdir -p $root/var/lib/tazpkg $root/etc
2760 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2761 cp -f /etc/slitaz-release $root/etc/slitaz-release
2762 strip_versions "$LIST_NAME"
2764 if [ "$REPACK" = 'y' ]; then
2765 # Determine full packages list with all dependencies
2766 tmp_dir="$(mktemp -d)"
2767 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2768 touch "$tmp_dir/full.pkglist"
2769 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2771 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2772 while read pkgname pkgver; do
2773 # Is package in full list?
2774 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2775 # Is package already repacked?
2776 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2777 _ 'Repacking %s...' "$pkgname-$pkgver"
2778 tazpkg repack "$pkgname" --quiet
2779 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2780 status
2781 done
2783 rm -r "$tmp_dir"
2784 fi
2786 if [ -f non-free.list ]; then
2787 # FIXME: working in the ROOTFS chroot?
2788 newline
2789 echo 'Preparing non-free packages...'
2790 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2791 while read pkg ; do
2792 if [ ! -d "$INSTALLED/$pkg" ]; then
2793 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2794 tazpkg get-install get-$pkg
2795 fi
2796 get-$pkg "$ROOTFS"
2797 fi
2798 tazpkg repack $pkg
2799 pkg=$(ls $pkg*.tazpkg)
2800 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2801 mv $pkg $PACKAGES_REPOSITORY
2802 done < non-free.list
2803 fi
2804 cp $LIST_NAME $DISTRO/distro-packages.list
2805 newline
2807 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2809 cd $DISTRO
2810 cp distro-packages.list $ROOTFS/etc/tazlito
2811 # Copy all files from $ADDFILES/rootfs to the rootfs.
2812 if [ -d "$ADDFILES/rootfs" ] ; then
2813 action 'Copying addfiles content to the rootfs...'
2814 cp -a $ADDFILES/rootfs/* $ROOTFS
2815 status
2816 fi
2818 action 'Root filesystem is generated...'; status
2820 # Root CD part.
2821 action 'Preparing the rootcd directory...'
2822 mkdir -p $ROOTCD
2823 status
2825 # Move the boot dir with the Linux kernel from rootfs.
2826 # The efi & boot dirs go directly on the CD.
2827 if [ -d "$ROOTFS/efi" ] ; then
2828 action 'Moving the efi directory...'
2829 mv $ROOTFS/efi $ROOTCD
2830 status
2831 fi
2832 if [ -d "$ROOTFS/boot" ] ; then
2833 action 'Moving the boot directory...'
2834 mv $ROOTFS/boot $ROOTCD
2835 status
2836 fi
2837 cd $DISTRO
2838 # Copy all files from $ADDFILES/rootcd to the rootcd.
2839 if [ -d "$ADDFILES/rootcd" ] ; then
2840 action 'Copying addfiles content to the rootcd...'
2841 cp -a $ADDFILES/rootcd/* $ROOTCD
2842 status
2843 fi
2844 # Execute the distro script used to perform tasks in the rootfs
2845 # before compression. Give rootfs path in arg
2846 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2847 if [ -x "$DISTRO_SCRIPT" ]; then
2848 echo 'Executing distro script...'
2849 sh $DISTRO_SCRIPT $DISTRO
2850 fi
2852 # Execute the custom_rules() found in receipt.
2853 if [ -s "$TOP_DIR/receipt" ]; then
2854 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2855 echo -e "Executing: custom_rules()\n"
2856 . "$TOP_DIR/receipt"
2857 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2858 fi
2859 fi
2861 # Multi-rootfs
2862 if [ -s /etc/tazlito/rootfs.list ]; then
2864 FLAVOR_LIST="$(awk '{
2865 for (i = 2; i <= NF; i+=2)
2866 printf "%s ", $i;
2867 }' /etc/tazlito/rootfs.list)"
2869 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2870 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2871 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2873 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2874 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2875 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2876 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2878 n=0
2879 last=$ROOTFS
2880 while read flavor; do
2881 n=$(($n+1))
2882 mkdir ${ROOTFS}0$n
2883 export root="${ROOTFS}0$n"
2884 # initial tazpkg setup in empty rootfs
2885 tazpkg --root=$root >/dev/null 2>&1
2887 newline
2888 boldify "Building $flavor rootfs..."
2890 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2891 cp "$TOP_DIR/$flavor.flavor" .
2893 if [ ! -s "$flavor.flavor" ]; then
2894 # We may have it in $FLAVORS_REPOSITORY
2895 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2896 tazlito pack-flavor $flavor
2897 else
2898 download $flavor.flavor
2899 fi
2900 fi
2902 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2903 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2904 cp $flavor.pkglist $DISTRO/list-packages0$n
2905 status
2907 strip_versions "$DISTRO/list-packages0$n"
2909 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2911 action 'Updating the boot directory...'
2912 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2913 rm -rf ${ROOTFS}0$n/boot
2915 cd $DISTRO
2916 if [ -s $flavor.rootfs ]; then
2917 _n 'Adding %s rootfs extra files...' "$flavor"
2918 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2919 fi
2921 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2922 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2923 status
2925 rm -f $flavor.flavor install-list
2926 mergefs ${ROOTFS}0$n $last
2927 last=${ROOTFS}0$n
2928 done <<EOT
2929 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2930 EOT
2931 #'
2932 i=$(($n+1))
2933 while [ $n -gt 0 ]; do
2934 mv ${ROOTFS}0$n ${ROOTFS}$i
2935 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2936 gen_initramfs ${ROOTFS}$i
2937 n=$(($n-1))
2938 i=$(($i-1))
2939 export LZMA_HISTORY_BITS=26
2940 done
2941 mv $ROOTFS ${ROOTFS}$i
2942 gen_initramfs ${ROOTFS}$i
2943 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2944 ROOTFS=${ROOTFS}1
2945 else
2946 # Initramfs and ISO image stuff.
2947 gen_initramfs $ROOTFS
2948 fi
2949 gen_livecd_isolinux
2950 distro_stats
2951 cleanup
2952 ;;
2955 clean-distro)
2956 # Remove old distro tree.
2958 check_root
2959 title 'Cleaning: %s' "$DISTRO"
2960 if [ -d "$DISTRO" ] ; then
2961 if [ -d "$ROOTFS" ] ; then
2962 action 'Removing the rootfs...'
2963 rm -f $DISTRO/$INITRAMFS
2964 rm -rf $ROOTFS
2965 status
2966 fi
2967 if [ -d "$ROOTCD" ] ; then
2968 action 'Removing the rootcd...'
2969 rm -rf $ROOTCD
2970 status
2971 fi
2972 action 'Removing eventual ISO image...'
2973 rm -f $DISTRO/$ISO_NAME.iso
2974 rm -f $DISTRO/$ISO_NAME.md5
2975 status
2976 fi
2977 footer
2978 ;;
2981 check-distro)
2982 # Check for a few LiveCD needed files not installed by packages.
2984 # TODO: Remove this function.
2985 # First two files are maintained by tazpkg while it runs on rootfs,
2986 # while last one file should be maintained by tazlito itself.
2987 check_rootfs
2988 title 'Checking distro: %s' "$ROOTFS"
2989 # SliTaz release info.
2990 rel='/etc/slitaz-release'
2991 if [ ! -f "$ROOTFS$rel" ]; then
2992 _ 'Missing release info: %s' "$rel"
2993 else
2994 action 'Release : %s' "$(cat $ROOTFS$rel)"
2995 status
2996 fi
2997 # Tazpkg mirror.
2998 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2999 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
3000 todomsg
3001 else
3002 action 'Mirror configuration exists...'
3003 status
3004 fi
3005 # Isolinux msg
3006 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
3007 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
3008 todomsg
3009 else
3010 action 'Isolinux message seems good...'
3011 status
3012 fi
3013 footer
3014 ;;
3017 writeiso)
3018 # Writefs to ISO image including /home unlike gen-distro we don't use
3019 # packages to generate a rootfs, we build a compressed rootfs with all
3020 # the current filesystem similar to 'tazusb writefs'.
3022 DISTRO='/home/slitaz/distro'
3023 ROOTCD="$DISTRO/rootcd"
3024 COMPRESSION="${2:-none}"
3025 ISO_NAME="${3:-slitaz}"
3026 check_root
3027 # Start info
3028 title 'Write filesystem to ISO'
3029 longline "The command writeiso will write the current filesystem into a \
3030 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3031 newline
3032 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3034 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3035 # Save some space
3036 rm -rf /var/cache/tazpkg/*
3037 rm -f /var/lib/tazpkg/*.bak
3038 rm -rf $DISTRO
3040 # Optionally remove sound card selection and screen resolution.
3041 if [ -z $LaunchedByTazpanel ]; then
3042 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3043 case $anser in
3044 y)
3045 action 'Removing current sound card and screen configurations...'
3046 rm -f /var/lib/sound-card-driver
3047 rm -f /var/lib/alsa/asound.state
3048 rm -f /etc/X11/xorg.conf ;;
3049 *)
3050 action 'Keeping current sound card and screen configurations...' ;;
3051 esac
3052 status
3053 newline
3055 # Optionally remove i18n settings
3056 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3057 case $anser in
3058 y)
3059 action 'Removing current locale/keymap settings...'
3060 newline > /etc/locale.conf
3061 newline > /etc/keymap.conf ;;
3062 *)
3063 action 'Keeping current locale/keymap settings...' ;;
3064 esac
3065 status
3066 fi
3068 # Clean-up files by default
3069 newline > /etc/udev/rules.d/70-persistent-net.rules
3070 newline > /etc/udev/rules.d/70-persistant-cd.rules
3072 # Create list of files including default user files since it is defined in /etc/passwd
3073 # and some new users might have been added.
3074 cd /
3075 echo 'init' > /tmp/list
3076 for dir in bin etc sbin var dev lib root usr home opt; do
3077 [ -d $dir ] && find $dir
3078 done >> /tmp/list
3080 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3081 [ -d $dir ] && echo $dir
3082 done >> /tmp/list
3084 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3086 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3087 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3088 #fi
3089 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3090 touch /var/log/wtmp
3092 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3093 sed -i "/var\/log\/$removelog/d" /tmp/list
3094 done
3096 # Generate initramfs with specified compression and display rootfs
3097 # size in realtime.
3098 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3100 write_initramfs &
3101 sleep 2
3102 cd - > /dev/null
3103 echo -en "\nFilesystem size:"
3104 while [ ! -f /tmp/rootfs ]; do
3105 sleep 1
3106 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3107 done
3108 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3109 echo -e "\n"
3110 rm -f /tmp/rootfs
3112 # Move freshly generated rootfs to the cdrom.
3113 mkdir -p $ROOTCD/boot
3114 mv -f /$INITRAMFS $ROOTCD/boot
3115 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3117 # Now we need the kernel and isolinux files.
3118 copy_from_cd() {
3119 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3120 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3121 unmeta_boot $ROOTCD
3122 umount /media/cdrom
3125 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3126 copy_from_cd;
3127 elif mount | grep /media/cdrom; then
3128 copy_from_cd;
3129 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3130 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3131 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3132 else
3133 touch /tmp/.write-iso-error
3134 longline "When SliTaz is running in RAM the kernel and bootloader \
3135 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3136 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3137 echo -en "----\nENTER to continue..."; read i
3138 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3139 copy_from_cd
3140 fi
3142 # Generate the iso image.
3143 touch /tmp/.write-iso
3144 newline
3145 cd $DISTRO
3146 create_iso $ISO_NAME.iso $ROOTCD
3147 action 'Creating the ISO md5sum...'
3148 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3149 status
3151 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3152 rm -f /tmp/.write-iso
3154 if [ -z $LaunchedByTazpanel ]; then
3155 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3156 case $anser in
3157 y)
3158 umount /dev/cdrom 2>/dev/null
3159 eject
3160 echo -n "Please insert a blank CD-ROM and press ENTER..."
3161 read i && sleep 2
3162 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3163 echo -en "----\nENTER to continue..."; read i ;;
3164 *)
3165 exit 0 ;;
3166 esac
3167 fi
3168 ;;
3171 burn-iso)
3172 # Guess CD-ROM device, ask user and burn the ISO.
3174 check_root
3175 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3176 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3177 # We can specify an alternative ISO from the cmdline.
3178 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3179 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3181 title 'Tazlito burn ISO'
3182 echo "CD-ROM device : /dev/$DRIVE_NAME"
3183 echo "Drive speed : $DRIVE_SPEED"
3184 echo "ISO image : $iso"
3185 footer
3187 case $(yesorno 'Burn ISO image?' 'n') in
3188 y)
3189 title 'Starting Wodim to burn the ISO...'
3190 sleep 2
3191 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3192 footer 'ISO image is burned to CD-ROM.'
3193 ;;
3194 *)
3195 die 'Exiting. No ISO burned.'
3196 ;;
3197 esac
3198 ;;
3201 merge)
3202 # Merge multiple rootfs into one iso.
3204 if [ -z "$2" ]; then
3205 cat <<EOT
3206 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3208 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3209 i.e: rootfsN is a subset of rootfsN-1
3210 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3211 The boot loader will select the rootfs according to the RAM size detected.
3213 Example:
3214 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3216 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3217 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3219 EOT
3220 exit 2
3221 fi
3223 shift # skip merge
3224 append="$1 slitaz1"
3225 shift # skip size1
3226 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3228 ISO=$1.merged
3230 # Extract filesystems
3231 action 'Mounting %s' "$1"
3232 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3233 status || cleanup_merge
3235 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3236 make_bzImage_hardlink $TMP_DIR/iso/boot
3237 umount -d $TMP_DIR/mnt
3238 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3239 _ '%s is already a merged iso. Aborting.' "$1"
3240 cleanup_merge
3241 fi
3242 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3243 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3244 if [ ! -f /boot/isolinux/ifmem.c32 -a
3245 ! -f /boot/isolinux/c32box.c32 ]; then
3246 cat <<EOT
3247 No file /boot/isolinux/ifmem.c32
3248 Please install syslinux package !
3249 EOT
3250 rm -rf $TMP_DIR
3251 exit 1
3252 fi
3253 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3254 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3255 fi
3257 action 'Extracting %s' 'iso/rootfs.gz'
3258 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3259 [ -d $TMP_DIR/rootfs1/etc ]
3260 status || cleanup_merge
3262 n=1
3263 while [ -n "$2" ]; do
3264 shift # skip rootfs N-1
3265 p=$n
3266 n=$(($n + 1))
3267 append="$append $1 slitaz$n"
3268 shift # skip size N
3269 mkdir -p $TMP_DIR/rootfs$n
3271 action 'Extracting %s' "$1"
3272 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3273 [ -d "$TMP_DIR/rootfs$n/etc" ]
3274 status || cleanup_merge
3276 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3277 action 'Creating %s' "rootfs$p.gz"
3278 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3279 status
3280 done
3281 action 'Creating %s' "rootfs$n.gz"
3282 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3283 status
3284 rm -f $TMP_DIR/iso/boot/rootfs.gz
3285 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3286 create_iso $ISO $TMP_DIR/iso
3287 rm -rf $TMP_DIR
3288 ;;
3291 repack)
3292 # Repack an iso with maximum lzma compression ratio.
3294 ISO=$2
3295 mkdir -p $TMP_DIR/mnt
3297 # Extract filesystems
3298 action 'Mounting %s' "$ISO"
3299 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3300 status || cleanup_merge
3302 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3303 umount -d $TMP_DIR/mnt
3305 for i in $TMP_DIR/iso/boot/rootfs* ; do
3306 action 'Repacking %s' "$(basename $i)"
3307 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3308 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3309 align_to_32bits $i
3310 status
3311 done
3313 create_iso $ISO $TMP_DIR/iso
3314 rm -rf $TMP_DIR
3315 ;;
3318 build-loram)
3319 # Build a Live CD for low RAM systems.
3321 ISO="$2"
3322 OUTPUT="$3"
3323 [ -z "$3" ] && \
3324 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3325 mkdir -p "$TMP_DIR/iso"
3326 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3327 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3328 if ! check_iso_for_loram ; then
3329 umount -d "$TMP_DIR/iso"
3330 die "$ISO is not a valid SliTaz live CD. Abort."
3331 fi
3332 case "$4" in
3333 cdrom) build_loram_cdrom ;;
3334 http) build_loram_http ;;
3335 *) build_loram_ram "$5" ;;
3336 esac
3337 umount $TMP_DIR/iso # no -d: needs /proc
3338 losetup -d $loopdev
3339 rm -rf $TMP_DIR
3340 ;;
3343 emu-iso)
3344 # Emulate an ISO image with Qemu.
3345 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3346 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3347 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3348 echo -e "\nStarting Qemu emulator:\n"
3349 echo -e "qemu $QEMU_OPTS $iso\n"
3350 qemu $QEMU_OPTS $iso
3351 ;;
3354 deduplicate)
3355 # Deduplicate files in a tree
3356 shift
3357 deduplicate "$@"
3358 ;;
3361 usage|*)
3362 # Print usage also for all unknown commands.
3363 usage
3364 ;;
3365 esac
3367 exit 0