tazlito view tazlito @ rev 516

tazlito: speedup deduplicate
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Jul 01 12:00:20 2019 +0200 (2019-07-01)
parents e2ff6056f93a
children c38700f27d76
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 cat > /tmp/cdsort$$ <<EOT
641 $PWD/boot/isolinux 100
642 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
643 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
644 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
645 $PWD/boot/isolinux/efi.img 300
646 $PWD/boot/isolinux/isolinux.bin 399
647 $PWD/boot/isolinux/boot.cat 400
648 EOT
650 action 'Computing md5...'
651 touch boot/isolinux/boot.cat
652 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
653 sort -k 2 > md5sum
654 status
656 cd - >/dev/null
657 title 'Generating ISO image'
659 _ 'Generating %s' "$1"
660 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
661 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
662 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
663 -no-emul-boot -boot-load-size 4 -boot-info-table \
664 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
665 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
666 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
667 -A "tazlito $VERSION/$(genisoimage --version)" \
668 -copyright README -P "www.slitaz.org" -no-pad $2
669 rm -f /tmp/cdsort$$
670 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
672 mkdir /tmp/mnt$$
673 mount -o loop,ro $1 /tmp/mnt$$
674 fixup_uefi_part $1 /tmp/mnt$$
675 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
676 ${uefi:+boot/isolinux/efi.img} ; do
677 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
678 done
679 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
680 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
681 umount -d /tmp/mnt$$
682 rmdir /tmp/mnt$$
684 if [ -s '/etc/tazlito/info' ]; then
685 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
686 action 'Storing ISO info...'
687 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
688 status
689 fi
690 fi
692 if [ -x '/usr/bin/isohybrid' ]; then
693 action 'Creating hybrid ISO...'
694 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
695 status
696 fi
698 if [ -x '/usr/bin/iso2exe' ]; then
699 echo 'Creating EXE header...'
700 /usr/bin/iso2exe $1 2>/dev/null
701 fi
702 }
705 # Generate a new ISO image using isolinux.
707 gen_livecd_isolinux() {
708 # Some packages may want to alter iso
709 genisohooks iso
710 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
712 # Set date for boot msg.
713 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
714 DATE=$(date +%Y%m%d)
715 action 'Setting build date to: %s...' "$DATE"
716 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
717 status
718 fi
720 cd $DISTRO
721 create_iso $ISO_NAME.iso $ROOTCD
723 action 'Creating the ISO md5sum...'
724 md5sum $ISO_NAME.iso > $ISO_NAME.md5
725 status
727 separator
728 # Some packages may want to alter final iso
729 genisohooks final
730 }
733 lzma_history_bits() {
734 #
735 # This generates an ISO which boots with Qemu but gives
736 # rootfs errors in frugal or liveUSB mode.
737 #
738 # local n
739 # local sz
740 # n=20 # 1Mb
741 # sz=$(du -sk $1 | cut -f1)
742 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
743 # n=$(( $n + 1 ))
744 # sz=$(( $sz / 2 ))
745 # done
746 # echo $n
747 echo ${LZMA_HISTORY_BITS:-24}
748 }
751 lzma_switches() {
752 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
753 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
754 }
757 lzma_set_size() {
758 # Update size field for lzma'd file packed using -si switch
759 return # Need to fix kernel code?
761 local n i
762 n=$(unlzma < $1 | wc -c)
763 for i in $(seq 1 8); do
764 printf '\\\\x%02X' $(($n & 255))
765 n=$(($n >> 8))
766 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
767 }
770 align_to_32bits() {
771 local size=$(stat -c %s ${1:-/dev/null})
772 [ $((${size:-0} & 3)) -ne 0 ] &&
773 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
774 }
777 dolz4() {
778 [ "$(which lz4)" ] || tazpkg get-install lz4
779 lz4 -9 > $1
780 }
783 dogzip() {
784 gzip -9 > $1
785 [ -x /usr/bin/advdef ] && advdef -qz4 $1
786 }
789 # Pack rootfs
791 pack_rootfs() {
792 ( cd $1; find . -print | cpio -o -H newc ) | \
793 case "$COMPRESSION" in
794 none)
795 _ 'Creating %s without compression...' 'initramfs'
796 cat > $2
797 ;;
798 lz4)
799 _ 'Creating %s with lz4 compression...' 'initramfs'
800 dolz4 $2
801 ;;
802 gzip)
803 _ 'Creating %s with gzip compression...' 'initramfs'
804 dogzip $2
805 ;;
806 *)
807 _ 'Creating %s with lzma compression...' 'initramfs'
808 lzma e -si -so $(lzma_switches $1) > $2
809 lzma_set_size $2
810 ;;
811 esac
812 align_to_32bits $2
813 echo 1 > /tmp/rootfs
814 }
817 # Compression functions for writeiso.
819 write_initramfs() {
820 case "$COMPRESSION" in
821 lzma)
822 _n 'Creating %s with lzma compression...' "$INITRAMFS"
823 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
824 align='y'
825 lzma_set_size "/$INITRAMFS"
826 ;;
827 gzip)
828 _ 'Creating %s with gzip compression...' "$INITRAMFS"
829 cpio -o -H newc | dogzip "/$INITRAMFS"
830 ;;
831 lz4)
832 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
833 cpio -o -H newc | dolz4 "/$INITRAMFS"
834 ;;
835 *)
836 # align='y'
837 _ 'Creating %s without compression...' "$INITRAMFS"
838 cpio -o -H newc > "/$INITRAMFS"
839 ;;
840 esac < /tmp/list
841 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
842 echo 1 > /tmp/rootfs
843 }
846 # Deduplicate files (MUST be on the same filesystem).
848 deduplicate() {
849 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
850 (
851 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
852 while read attr inode link file; do
853 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
854 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
855 rm -f "$file"
856 if ln "$old_file" "$file" 2>/dev/null; then
857 hinode="$inode"
858 inode="$old_inode"
859 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
860 save="$(($save+(${attr%%-*}+512)/1024))"
861 continue
862 else
863 cp -p "$old_file" "$file"
864 fi
865 else
866 hinode=""
867 fi
868 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
869 done
870 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
871 )
873 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
874 while read attr inode link file; do
875 echo "$attr-$(readlink "$file" | uuencode -m - | \
876 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
877 done | sort | \
878 (
879 old_attr=""; hardlinks=0;
880 while read attr inode link file; do
881 if [ "$attr" = "$old_attr" ]; then
882 if [ "$inode" != "$old_inode" ]; then
883 rm -f "$file"
884 if ln "$old_file" "$file" 2>/dev/null; then
885 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
886 else
887 cp -a "$old_file" "$file"
888 fi
889 fi
890 else
891 old_file="$file"
892 old_attr="$attr"
893 old_inode="$inode"
894 fi
895 done
896 _ '%s duplicate symlinks.' "$hardlinks"
897 )
898 }
901 # Generate a new initramfs from the root filesystem.
903 gen_initramfs() {
904 # Just in case CTRL+c
905 rm -f $DISTRO/gen
907 # Some packages may want to alter rootfs
908 genisohooks rootfs
909 cd $1
911 # Normalize file time
912 find $1 -newer $1 -exec touch -hr $1 {} \;
914 # Link duplicate files
915 deduplicate
917 # Use lzma if installed. Display rootfs size in realtime.
918 rm -f /tmp/rootfs 2>/dev/null
919 pack_rootfs . $DISTRO/$(basename $1).gz &
920 sleep 2
921 echo -en "\nFilesystem size:"
922 while [ ! -f /tmp/rootfs ]; do
923 sleep 1
924 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
925 done
926 echo -e "\n"
927 rm -f /tmp/rootfs
928 cd $DISTRO
929 mv $(basename $1).gz $ROOTCD/boot
930 }
933 distro_sizes() {
934 if [ -n "$start_time" ]; then
935 time=$(($(date +%s) - $start_time))
936 sec=$time
937 div=$(( ($time + 30) / 60))
938 [ "$div" -ne 0 ] && min="~ ${div}m"
939 _ 'Build time : %ss %s' "$sec" "$min"
940 fi
941 cat <<EOT
942 Build date : $(date +%Y%m%d)
943 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
944 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
945 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
946 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
947 EOT
948 footer "Image is ready: $ISO_NAME.iso"
949 }
952 # Print ISO and rootfs size.
954 distro_stats() {
955 title 'Distro statistics: %s' "$DISTRO"
956 distro_sizes
957 }
960 # Create an empty configuration file.
962 empty_config_file() {
963 cat >> tazlito.conf <<"EOF"
964 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
965 #
967 # Name of the ISO image to generate.
968 ISO_NAME=""
970 # ISO image volume name.
971 VOLUM_NAME="SliTaz"
973 # Name of the preparer.
974 PREPARED="$USER"
976 # Path to the packages repository and the packages.list.
977 PACKAGES_REPOSITORY=""
979 # Path to the distro tree to gen-distro from a list of packages.
980 DISTRO=""
982 # Path to the directory containing additional files
983 # to copy into the rootfs and rootcd of the LiveCD.
984 ADDFILES="$DISTRO/addfiles"
986 # Default answer for binary question (Y or N)
987 DEFAULT_ANSWER="ASK"
989 # Compression utility (lzma, gzip or none)
990 COMPRESSION="lzma"
991 EOF
992 }
995 # Extract rootfs.gz somewhere
997 extract_rootfs() {
998 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
999 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1000 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1001 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1002 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
1006 # Extract flavor file to temp directory
1008 extract_flavor() {
1009 # Input: $1 - flavor name to extract;
1010 # $2 = absent/empty: just extract 'outer layer'
1011 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1012 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1013 # Output: temp dir path where flavor was extracted
1014 local f="$1.flavor" from to infos="$1.desc"
1015 [ -f "$f" ] || die "File '$f' not found"
1016 local dir="$(mktemp -d)"
1017 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1019 if [ -n "$2" ]; then
1020 cd $dir
1022 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1024 for i in rootcd rootfs; do
1025 [ -f "$1.$i" ] || continue
1026 mkdir "$i"
1027 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1028 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1029 rm "$1.$i"
1030 done
1031 touch -t 197001010100.00 $1.*
1032 # Info to be stored inside ISO
1033 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1034 rm $1.list*
1036 # Renames
1037 while read from to; do
1038 [ -f "$from" ] || continue
1039 mv "$from" "$to"
1040 done <<EOT
1041 $1.nonfree non-free.list
1042 $1.pkglist packages.list
1043 $1-distro.sh distro.sh
1044 $1.receipt receipt
1045 $1.mirrors mirrors
1046 $1.desc description
1047 EOT
1048 fi
1050 echo $dir
1054 # Pack flavor file from temp directory
1056 pack_flavor() {
1057 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1061 # Remove duplicate files
1063 files_match() {
1064 if [ -d "$1" ]; then
1065 return 1
1067 elif [ -L "$1" ] && [ -L "$2" ]; then
1068 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1070 elif [ -f "$1" ] && [ -f "$2" ]; then
1071 cmp -s "$1" "$2" && return 0
1073 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1074 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1075 return 0
1077 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1078 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1079 return 0
1081 fi 2> /dev/null
1082 return 1
1085 remove_with_path() {
1086 dir="$(dirname $1)"
1087 rm -f "$1"
1088 while rmdir "$dir" 2> /dev/null; do
1089 dir="$(dirname $dir)"
1090 done
1093 mergefs() {
1094 # Note, many packages have files with spaces in the name
1095 IFS=$'\n'
1097 local size1=$(du -hs "$1" | awk '{ print $1 }')
1098 local size2=$(du -hs "$2" | awk '{ print $1 }')
1099 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1101 # merge symlinks files and devices
1102 ( cd "$1"; find ) | \
1103 while read file; do
1104 files_match "$1/$file" "$2/$file" "$file" &&
1105 remove_with_path "$2/$file"
1106 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1107 done
1109 unset IFS
1110 status
1114 cleanup_merge() {
1115 rm -rf $TMP_DIR
1116 exit 1
1120 # Update isolinux config files for multiple rootfs
1122 update_bootconfig() {
1123 local files
1124 action 'Updating boot config files...'
1125 files="$(grep -l 'include common' $1/*.cfg)"
1126 for file in $files; do
1127 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1128 if (/label/) label=$0;
1129 else if (/kernel/) kernel=$0;
1130 else if (/append/) {
1131 i=index($0,"rootfs.gz");
1132 append=substr($0,i+9);
1134 else if (/include/) {
1135 for (i = 1; i <= n; i++) {
1136 print label i
1137 print kernel;
1138 initrd="initrd=/boot/rootfs" n ".gz"
1139 for (j = n - 1; j >= i; j--) {
1140 initrd=initrd ",/boot/rootfs" j ".gz";
1142 printf "\tappend %s%s\n",initrd,append;
1143 print "";
1145 print;
1147 else print;
1148 }' < $file > $file.$$
1149 mv -f $file.$$ $file
1150 done
1151 sel="$(echo $2 | awk '{
1152 for (i=1; i<=NF; i++)
1153 if (i % 2 == 0) printf " slitaz%d", i/2
1154 else printf " %s", $i
1155 }')"
1157 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1159 label slitaz
1160 kernel /boot/isolinux/ifmem.c32
1161 append$sel noram
1163 label noram
1164 config noram.cfg
1166 EOT
1168 # Update vesamenu
1169 if [ -s "$1/isolinux.cfg" ]; then
1170 files="$files $1/isolinux.cfg"
1171 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1172 BEGIN {
1173 kernel = " COM32 c32box.c32"
1176 if (/ROWS/) print "MENU ROWS " n+$3;
1177 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1178 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1179 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1180 else if (/VSHIFT/) {
1181 x = $3-n;
1182 if (x < 0) x = 0;
1183 print "MENU VSHIFT " x;
1185 else if (/rootfs.gz/) {
1186 linux = "";
1187 if (/bzImage/) linux = "linux /boot/bzImage ";
1188 i = index($0, "rootfs.gz");
1189 append = substr($0, i+9);
1190 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1191 printf "\tappend%s noram\n", sel;
1192 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1193 for (i = 1; i <= n; i++) {
1194 print "LABEL slitaz" i
1195 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1196 printf "%s\n", kernel;
1197 initrd = "initrd=/boot/rootfs" n ".gz"
1198 for (j = n - 1; j >= i; j--) {
1199 initrd = initrd ",/boot/rootfs" j ".gz";
1201 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1204 else if (/bzImage/) kernel = $0;
1205 else print;
1206 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1207 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1208 fi
1210 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1211 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1212 cat > $1/noram.cfg <<EOT
1213 implicit 0
1214 prompt 1
1215 timeout 80
1216 $(grep '^F[0-9]' $1/isolinux.cfg)
1218 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1219 say Not enough RAM to boot slitaz. Trying hacker mode...
1220 default hacker
1221 label hacker
1222 KERNEL /boot/bzImage
1223 append rw root=/dev/null vga=normal
1225 label reboot
1226 EOT
1228 if [ -s $1/c32box.c32 ]; then
1229 cat >> $1/noram.cfg <<EOT
1230 COM32 c32box.c32
1231 append reboot
1233 label poweroff
1234 COM32 c32box.c32
1235 append poweroff
1237 EOT
1238 else
1239 echo " com32 reboot.c32" >> $1/noram.cfg
1240 fi
1242 # Restore real label names
1243 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1244 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1245 while read pat; do
1246 sed -i "s/slitaz$pat/" $files
1247 done
1248 status
1252 # Uncompress rootfs or module to stdout
1254 uncompress() {
1255 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1256 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1260 # Install a missing package
1262 install_package() {
1263 if [ -z "$2" ]; then
1264 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1265 else
1266 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1267 fi
1268 case "$answer" in
1269 y)
1270 # We don't want package on host cache.
1271 action 'Getting and installing package: %s' "$1"
1272 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1273 status ;;
1274 *)
1275 return 1 ;;
1276 esac
1280 # Check iso for loram transformation
1282 check_iso_for_loram() {
1283 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1284 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1288 # Remove duplicated files in $1/efi/boot from $1/boot
1290 cleanup_efi_boot() {
1291 [ -s $1/boot/isolinux/efi.img ] &&
1292 [ ! -x $1/boot/isolinux/efi.img ] &&
1293 rm -f $1/boot/isolinux/efi.img
1294 for i in $1/efi/boot/* ; do
1295 [ -f $i ] || continue
1296 case "$i" in
1297 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1298 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1299 rm $1/efi/boot/linux.cmdline ;;
1300 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1301 rm $1/efi/boot/linux.cmdline* ;;
1302 esac
1303 rm -f $i
1304 rmdir $1/efi/boot && rmdir $1/efi
1305 done 2> /dev/null
1309 # Build initial rootfs for loram ISO ram/cdrom/http
1311 build_initfs() {
1312 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1313 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1314 mirror3.slitaz.org mirror.slitaz.org"
1315 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1316 [ -z "$version" ] && die "Can't find the kernel version." \
1317 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1319 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1320 need_lib=false
1321 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1322 mkdir -p $TMP_DIR/initfs/$i
1323 done
1324 ln -s bin $TMP_DIR/initfs/sbin
1325 ln -s . $TMP_DIR/initfs/usr
1326 for aufs in aufs overlayfs; do
1327 for v in $version ; do
1328 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1329 install_package ${v/*taz/linux}-$aufs $v && continue
1330 done
1331 install_package $aufs $version && break
1332 done || return 1
1333 [ -s /init ] || install_package slitaz-boot-scripts
1334 cp /init $TMP_DIR/initfs/
1335 for v in $version ; do
1336 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1337 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1338 done
1339 if [ "$1" = 'cdrom' ]; then
1340 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1341 else
1342 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1343 for v in $version ; do
1344 while [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; do
1345 install_package linux-squashfs $v || return 1
1346 done
1347 done
1348 for v in $version ; do
1349 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1350 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1351 done
1352 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1353 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1354 fi
1355 if [ "$1" = 'http' ]; then
1356 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1357 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1358 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1359 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1360 cp -a /dev/fuse $TMP_DIR/initfs/dev
1361 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1362 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1363 else
1364 need_lib=true
1365 fi
1366 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1367 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1368 else
1369 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1370 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1371 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1372 cp -a /lib/librt* $TMP_DIR/initfs/lib
1373 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1374 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1375 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1376 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1377 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1378 need_lib=true
1379 fi
1380 cd $TMP_DIR/fs
1381 echo 'Getting slitaz-release & ethernet modules...'
1382 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1383 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1384 [ -s rootfs* ] || continue
1385 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1386 rm -f rootfs*
1387 done 2>&1 > /dev/null
1388 cd - > /dev/null
1389 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1390 for v in $version ; do
1391 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1392 -type f -name '*.ko*' | while read mod; do
1393 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1394 uncompress $mod > $f
1395 grep -q alias=pci: $f || rm -f $f
1396 done
1397 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1398 f=$(basename $i)..z
1399 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1400 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1401 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1402 for j in $deps; do
1403 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1404 uncompress $mod > $(echo $j | sed s/..z$//)
1405 done
1406 done
1407 done
1408 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"
1409 _n 'List of URLs to insert: '
1410 read -t 30 urliso2
1411 urliso="$urliso2 $urliso"
1412 fi
1413 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1414 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1415 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1416 else
1417 cp /bin/busybox $TMP_DIR/initfs/bin
1418 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1419 cp /sbin/insmod $TMP_DIR/initfs/bin
1420 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1421 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1422 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1423 fi
1424 need_lib=true
1425 fi
1426 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1427 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1428 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1429 done
1430 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1431 for v in $version ; do
1432 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1433 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1434 done
1435 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1436 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1437 cp -a $i $TMP_DIR/initfs/dev
1438 done
1439 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1440 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1441 cp -a $i $TMP_DIR/initfs/dev
1442 done 2>/dev/null
1443 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1444 cp -a $i $TMP_DIR/initfs/lib
1445 done
1446 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1447 #!/bin/sh
1449 getarg() {
1450 grep -q " \$1=" /proc/cmdline || return 1
1451 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1452 return 0
1455 copy_rootfs() {
1456 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1457 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1458 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1459 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1460 path=/mnt/
1461 return 0
1462 else
1463 rm -f /mnt/rootfs*
1464 return 1
1465 fi
1468 echo "Switching / to tmpfs..."
1469 mount -t proc proc /proc
1470 size="\$(grep rootfssize= < /proc/cmdline | \\
1471 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1472 [ -n "\$size" ] || size="-o size=90%"
1474 mount -t sysfs sysfs /sys
1475 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1476 [ -s \$i ] && continue
1477 echo -en "Probe \$i \\r"
1478 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1479 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1480 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1481 insmod /lib/modules/\$k.ko 2> /dev/null
1482 done
1483 echo "Loading \$i"
1484 insmod \$i 2> /dev/null
1485 break
1486 done
1487 done
1488 umount /sys
1489 while read var default; do
1490 eval \$var=\$default
1491 getarg \$var \$var
1492 done <<EOT
1493 eth eth0
1494 dns 208.67.222.222,208.67.220.220
1495 netmask 255.255.255.0
1496 gw
1497 ip
1498 EOT
1499 grep -q \$eth /proc/net/dev || sh
1500 if [ -n "\$ip" ]; then
1501 ifconfig \$eth \$ip netmask \$netmask up
1502 route add default gateway \$gw
1503 for i in \$(echo \$dns | sed 's/,/ /g'); do
1504 echo "nameserver \$i" >> /etc/resolv.conf
1505 done
1506 else
1507 udhcpc -f -q -s /lib/udhcpc -i \$eth
1508 fi
1509 for i in $urliso ; do
1510 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1511 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"
1512 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1513 done
1514 getarg urliso URLISO
1515 DIR=fs
1516 if getarg loram DIR; then
1517 DEVICE=\${DIR%,*}
1518 DIR=/\${DIR#*,}
1519 fi
1520 mount -t tmpfs \$size tmpfs /mnt
1521 path2=/mnt/.httpfs/
1522 path=/mnt/.cdrom/
1523 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1524 while [ ! -d \$path/boot ]; do
1525 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1526 httpfs \$i \$path2 && echo \$i && break
1527 done
1528 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1529 done
1531 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1532 umount /proc
1533 branch=:/mnt/.cdrom/\$DIR
1534 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1535 branch=
1536 lp=1
1537 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1538 [ -s \$i ] && insmod \$i
1539 done 2> /dev/null
1540 for i in \${path}boot/rootfs?.* ; do
1541 fs=\${i#*root}
1542 branch=\$branch:/mnt/.\$fs
1543 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1544 losetup -o 124 /dev/loop\$lp \$i
1545 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1546 lp=\$((\$lp+1))
1547 done
1548 fi
1549 mkdir -p /mnt/.rw/mnt/.httpfs
1550 while read type opt; do
1551 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1552 [ -s \$i ] && insmod \$i &&
1553 mount -t \$type -o \$opt none /mnt && break 2
1554 done
1555 done <<EOT
1556 aufs br=/mnt/.rw\$branch
1557 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1558 EOT
1559 rm -rf /lib/modules
1560 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1561 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1562 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1563 EOTEOT
1564 chmod +x $TMP_DIR/initfs/init
1565 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1566 [ -s $i ] || continue
1567 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1568 rm -f $i
1569 done 2>/dev/null
1570 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1571 lzma e $TMP_DIR/initfs.gz -si
1572 lzma_set_size $TMP_DIR/initfs.gz
1573 rm -rf $TMP_DIR/initfs
1574 align_to_32bits $TMP_DIR/initfs.gz
1575 return 0
1579 # Move each initramfs to squashfs
1581 build_loram_rootfs() {
1582 rootfs_sizes=""
1583 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1584 mkdir -p $TMP_DIR/fs
1585 cd $TMP_DIR/fs
1586 uncompress $i | cpio -idm
1587 deduplicate
1588 cd - > /dev/null
1589 rootfs=$TMP_DIR/$(basename $i 64)
1590 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1591 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1592 cd $TMP_DIR
1593 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1594 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1595 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1596 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1597 rm -f $rootfs
1598 mv ${rootfs%64}.cpio $rootfs
1599 cd - > /dev/null
1600 rm -rf $TMP_DIR/fs
1601 done
1605 # Move meta boot configuration files to basic configuration files
1606 # because meta loram flavor is useless when rootfs is not loaded in RAM
1608 unmeta_boot() {
1609 local root=${1:-$TMP_DIR/loramiso}
1610 if [ -f $root/boot/isolinux/noram.cfg ]; then
1611 # We keep enough information to do unloram...
1612 [ -s $root/boot/isolinux/common.cfg ] &&
1613 sed -i 's/label slitaz/label orgslitaz/' \
1614 $root/boot/isolinux/common.cfg
1615 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1616 shift
1617 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1618 $root/boot/isolinux/isolinux.cfg
1619 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1620 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1621 $root/boot/isolinux/*.cfg
1622 fi
1626 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1627 # These squashfs may be loaded in RAM at boot time.
1628 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1629 # Meta flavors are converted to normal flavors.
1631 build_loram_cdrom() {
1632 build_initfs cdrom || return 1
1633 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1634 cleanup_efi_boot $TMP_DIR/loramiso
1635 mkdir $TMP_DIR/loramiso/fs
1636 cd $TMP_DIR/loramiso/fs
1637 for i in $( ls ../boot/root* | sort -r ) ; do
1638 uncompress $i | cpio -idmu
1639 rm -f $i
1640 done
1641 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1642 cd - >/dev/null
1643 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1644 unmeta_boot
1645 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1646 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1647 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1648 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1649 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1650 create_iso $OUTPUT $TMP_DIR/loramiso
1654 # Create http bootstrap to load and remove loram_cdrom
1655 # Meta flavors are converted to normal flavors.
1657 build_loram_http() {
1658 build_initfs http || return 1
1659 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1660 cleanup_efi_boot $TMP_DIR/loramiso
1661 rm -f $TMP_DIR/loramiso/boot/rootfs*
1662 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1663 unmeta_boot
1664 create_iso $OUTPUT $TMP_DIR/loramiso
1668 # Update meta flavor selection sizes.
1669 # Reduce sizes with rootfs gains.
1671 update_metaiso_sizes() {
1672 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1673 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1674 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1675 do
1676 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1677 local sizes="$rootfs_sizes"
1678 local new
1679 set -- $append
1680 shift
1681 [ "$1" = "ifmem" ] && shift
1682 new=""
1683 while [ -n "$2" ]; do
1684 local s
1685 case "$1" in
1686 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1687 *M) s=$(( ${1%M} * 1024 ));;
1688 *) s=${1%K};;
1689 esac
1690 sizes=${sizes#* }
1691 for i in $sizes ; do
1692 s=$(( $s - $i ))
1693 done
1694 new="$new $s $2"
1695 shift 2
1696 done
1697 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1698 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1699 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1700 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1701 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1702 done
1706 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1707 # Meta flavor selection sizes are updated.
1709 build_loram_ram() {
1710 build_initfs ram || return 1
1711 build_loram_rootfs "$1"
1712 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1713 cleanup_efi_boot $TMP_DIR/loramiso
1714 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1715 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1716 update_metaiso_sizes
1717 create_iso $OUTPUT $TMP_DIR/loramiso
1721 # Remove files installed by packages
1723 find_flavor_rootfs() {
1724 for i in $1/etc/tazlito/*.extract; do
1725 [ -e $i ] || continue
1726 chroot $1 /bin/sh ${i#$1}
1727 done
1729 # Clean hardlinks and files patched by genisofs in /boot
1730 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1731 rm -f $1/boot/$i*
1732 done
1734 # Clean files generated in post_install
1735 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1736 $1/dev/core $1/dev/fd $1/dev/std*
1738 # Verify md5
1739 cat $1$INSTALLED/*/md5sum | \
1740 while read md5 file; do
1741 [ -e "$1$file" ] || continue
1742 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1743 rm -f "$1$file"
1744 done
1746 # Check configuration files
1747 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1748 [ -e $i ] || continue
1749 mkdir /tmp/volatile$$
1750 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1751 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1752 while read file ; do
1753 [ -e "$1/$file" ] || continue
1754 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1755 done
1756 rm -rf /tmp/volatile$$
1757 done
1759 # Remove other files blindly
1760 for i in $1$INSTALLED/*/files.list; do
1761 for file in $(cat "$i"); do
1762 [ "$1$file" -nt "$i" ] && continue
1763 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1764 [ -d "$1$file" ] || rm -f "$1$file"
1765 done
1766 done
1768 # Remove tazpkg files and tmp files
1769 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1770 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1771 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1772 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1773 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1775 # Cleanup directory tree
1776 cd $1
1777 find * -type d | sort -r | while read dir; do
1778 rmdir "$dir" 2>/dev/null
1779 done
1780 cd - > /dev/null
1784 # Get byte(s) from a binary file
1786 get() {
1787 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1791 # Get cpio flavor info from the ISO image
1793 flavordata() {
1794 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1795 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1799 # Restore undigest mirrors
1801 restore_mirrors() {
1802 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1803 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1805 action 'Restoring mirrors...'
1806 if [ -d "$undigest.bak" ]; then
1807 [ -d "$undigest" ] && rm -r "$undigest"
1808 mv "$undigest.bak" "$undigest"
1809 fi
1810 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1811 :; status
1815 # Setup undigest mirrors
1817 setup_mirrors() {
1818 # Setup mirrors in plain system or in chroot (with variable root=)
1819 local mirrorlist="$1" fresh repacked
1820 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1822 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1823 restore_mirrors
1825 _ 'Setting up mirrors for %s...' "$root/"
1826 # Backing up current undigest mirrors and priority
1827 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1828 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1829 rm -rf '/var/www/tazlito/'
1830 mkdir -p '/var/www/tazlito/'
1832 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1833 fresh='/home/slitaz/packages'
1834 if [ -d "$fresh" ]; then
1835 # Setup first undigest mirror
1836 mkdir -p "$undigest/fresh"
1837 echo "$fresh" > "$undigest/fresh/mirror"
1838 echo 'fresh' >> "$priority"
1839 # Rebuild mirror DB if needed
1840 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1841 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1842 tazpkg mkdb "$fresh" --forced --root=''
1843 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1844 fi
1846 # Repacked packages: high priority
1847 repacked="$PACKAGES_REPOSITORY"
1848 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1849 # According to Tazlito setup file (tazlito.conf):
1850 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1851 # or
1852 # WORK_DIR="/home/slitaz"
1853 # and
1854 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1855 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1857 # Setup second undigest mirror
1858 mkdir -p "$undigest/repacked"
1859 echo "$repacked" > "$undigest/repacked/mirror"
1860 echo 'repacked' >> "$priority"
1861 # Rebuild mirror DB if needed
1862 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1863 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1864 tazpkg mkdb "$repacked" --forced --root=''
1865 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1866 fi
1868 # All repositories listed in mirrors list: normal priority
1869 [ -e "$mirrorlist" ] && \
1870 while read mirror; do
1871 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1872 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1873 mkdir -p "$undigest/$mirrorid"
1874 echo "$mirror" > "$undigest/$mirrorid/mirror"
1875 echo "$mirrorid" >> "$priority"
1876 done < "$mirrorlist"
1878 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1880 # Show list of mirrors
1881 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1882 function show(num, name, url) {
1883 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1886 num++;
1887 "cat " db "/undigest/" $0 "/mirror" | getline url;
1888 show(num, $0, url);
1890 END {
1891 num++;
1892 "cat " db "/mirror" | getline url;
1893 show(num, "main", url);
1894 }' "$priority"
1896 tazpkg recharge --quiet >/dev/null
1900 # Get list of 'packages.info' lists using priority
1902 pi_lists() {
1903 local pi
1904 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1905 local priority="$root$LOCALSTATE/priority"
1906 local undigest="$root$LOCALSTATE/undigest"
1909 [ -s "$priority" ] && cat "$priority"
1910 echo 'main'
1911 [ -d "$undigest" ] && ls "$undigest"
1912 } | awk -vun="$undigest/" '
1914 if (arr[$0] != 1) {
1915 arr[$0] = 1;
1916 print un $0 "/packages.info";
1918 }' | sed 's|/undigest/main||' | \
1919 while read pi; do
1920 [ -e "$pi" ] && echo "$pi"
1921 done
1925 # Strip versions from packages list
1927 strip_versions() {
1928 if [ -n "$stripped" ]; then
1929 action 'Consider list %s already stripped' "$(basename "$1")"
1930 status
1931 return 0
1932 fi
1933 action 'Strip versions from list %s...' "$(basename "$1")"
1934 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1935 [ -f "$in_list" ] || die "List '$in_list' not found."
1937 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1938 awk '
1940 if (FILENAME ~ "packages.info") {
1941 # Collect package names
1942 FS = "\t"; pkg[$1] = 1;
1943 } else {
1944 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1945 while (NF > 1 && ! pkg[$0])
1946 NF --;
1947 printf "%s\n", $0;
1949 }' $(pi_lists) "$in_list" > "$tmp_list"
1951 cat "$tmp_list" > "$in_list"
1952 rm "$tmp_list"
1953 status
1957 # Display list of unknown packages (informative)
1959 display_unknown() {
1960 [ -s "$1" ] || return
1961 echo "Unknown packages:" >&2
1962 cat "$1" >&2
1963 rm "$1"
1967 # Display warnings about critical packages absent (informative)
1969 display_warn() {
1970 [ -s "$1" ] || return
1971 echo "Absent critical packages:" >&2
1972 cat "$1" >&2
1973 rm "$1"
1974 echo "Probably ISO image will be unusable."
1978 # Install packages to rootfs
1980 install_list_to_rootfs() {
1981 local list="$1" rootfs="$2" pkg i ii
1982 local undigest="$rootfs/var/lib/tazpkg/undigest"
1984 # initial tazpkg setup in empty rootfs
1985 tazpkg --root=$rootfs >/dev/null 2>&1
1986 # pass current 'mirror' to the rootfs
1987 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1988 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1989 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1990 # link rootfs packages cache to the regular packages cache
1991 rm -r "$rootfs/var/cache/tazpkg"
1992 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1994 setup_mirrors mirrors
1996 # Just in case if flavor doesn't contain "tazlito" package
1997 mkdir -p "$rootfs/etc/tazlito"
1999 newline
2001 # Choose detailed log with --detailed
2002 if [ -n "$detailed" ]; then
2003 while read pkg; do
2004 separator '-'
2005 echo $pkg
2006 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2007 done < $list
2008 separator '='
2009 else
2010 while read pkg; do
2011 action 'Installing package: %s' "$pkg"
2012 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2013 status
2014 done < $list
2015 fi
2016 newline
2018 restore_mirrors
2019 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2020 for i in fresh repacked; do
2021 ii="$undigest/$i"
2022 [ -d "$ii" ] && rm -rf "$ii"
2023 ii="$rootfs/var/lib/tazpkg/priority"
2024 if [ -f "$ii" ]; then
2025 sed -i "/$i/d" "$ii"
2026 [ -s "$ii" ] || rm "$ii"
2027 fi
2028 done
2029 [ -d "$undigest" ] && \
2030 for i in $(find "$undigest" -type f); do
2031 # Remove all undigest PKGDB files but 'mirror'
2032 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2033 done
2034 [ -d "$undigest" ] && \
2035 rmdir --ignore-fail-on-non-empty "$undigest"
2037 # Un-link packages cache
2038 rm "$rootfs/var/cache/tazpkg"
2040 # Clean /var/lib/tazpkg
2041 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2047 ####################
2048 # Tazlito commands #
2049 ####################
2051 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2052 case "$0" in
2053 *reduplicate)
2054 find ${@:-.} ! -type d -links +1 \
2055 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2056 exit 0 ;;
2057 *deduplicate)
2058 deduplicate "$@"
2059 exit 0 ;;
2060 esac
2063 case "$COMMAND" in
2064 stats)
2065 # Tazlito general statistics from the config file.
2067 title 'Tazlito statistics'
2068 optlist "\
2069 Config file : $CONFIG_FILE
2070 ISO name : $ISO_NAME.iso
2071 Volume name : $VOLUM_NAME
2072 Prepared : $PREPARED
2073 Packages repository : $PACKAGES_REPOSITORY
2074 Distro directory : $DISTRO
2075 Additional files : $ADDFILES
2076 " | sed '/: $/d'
2077 footer
2078 ;;
2081 list-addfiles)
2082 # Simple list of additional files in the rootfs
2083 newline
2084 if [ -d "$ADDFILES/rootfs" ]; then
2085 cd $ADDFILES
2086 find rootfs -type f
2087 else
2088 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2089 fi
2090 newline
2091 ;;
2094 gen-config)
2095 # Generate a new config file in the current dir or the specified
2096 # directory by $2.
2098 if [ -n "$2" ]; then
2099 mkdir -p "$2" && cd "$2"
2100 fi
2102 newline
2103 action 'Generating empty tazlito.conf...'
2104 empty_config_file
2105 status
2107 separator
2108 if [ -f 'tazlito.conf' ] ; then
2109 _ 'Configuration file is ready to edit.'
2110 _ 'File location: %s' "$(pwd)/tazlito.conf"
2111 newline
2112 fi
2113 ;;
2116 configure)
2117 # Configure a tazlito.conf config file. Start by getting
2118 # a empty config file and sed it.
2120 if [ -f 'tazlito.conf' ]; then
2121 rm tazlito.conf
2122 else
2123 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2124 'or in the same directory of the file you want to configure.'
2125 cd /etc
2126 fi
2128 empty_config_file
2130 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2132 # ISO name.
2133 echo -n "ISO name : " ; read answer
2134 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2135 # Volume name.
2136 echo -n "Volume name : " ; read answer
2137 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2138 # Packages repository.
2139 echo -n "Packages repository : " ; read answer
2140 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2141 # Distro path.
2142 echo -n "Distro path : " ; read answer
2143 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2144 footer "Config file is ready to use."
2145 echo 'You can now extract an ISO or generate a distro.'
2146 newline
2147 ;;
2150 gen-iso)
2151 # Simply generate a new iso.
2153 check_root
2154 verify_rootcd
2155 gen_livecd_isolinux
2156 distro_stats
2157 ;;
2160 gen-initiso)
2161 # Simply generate a new initramfs with a new iso.
2163 check_root
2164 verify_rootcd
2165 gen_initramfs "$ROOTFS"
2166 gen_livecd_isolinux
2167 distro_stats
2168 ;;
2171 extract-distro|extract-iso)
2172 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2174 check_root
2175 ISO_IMAGE="$2"
2176 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2177 'Example:\n tazlito image.iso /path/target'
2179 # Set the distro path by checking for $3 on cmdline.
2180 TARGET="${3:-$DISTRO}"
2182 # Exit if existing distro is found.
2183 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2184 'Please clean the distro tree or change directory path.'
2186 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2188 # Start to mount the ISO.
2189 action 'Mounting ISO image...'
2190 mkdir -p "$TMP_DIR"
2191 # Get ISO file size.
2192 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2193 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2194 sleep 2
2195 # Prepare target dir, copy the kernel and the rootfs.
2196 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2197 status
2199 action 'Copying the Linux kernel...'
2200 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2201 make_bzImage_hardlink "$TARGET/rootcd/boot"
2202 else
2203 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2204 fi
2205 status
2207 for i in $(ls $TMP_DIR); do
2208 [ "$i" = 'boot' ] && continue
2209 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2210 done
2212 for loader in isolinux syslinux extlinux grub; do
2213 [ -d "$TMP_DIR/boot/$loader" ] || continue
2214 action 'Copying %s files...' "$loader"
2215 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2216 status
2217 done
2219 action 'Copying the rootfs...'
2220 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2221 status
2223 cleanup_efi_boot "$TARGET/rootcd"
2225 # Extract initramfs.
2226 cd "$TARGET/rootfs"
2227 action 'Extracting the rootfs...'
2228 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2229 extract_rootfs "$i" "$TARGET/rootfs"
2230 done
2231 # unpack /usr
2232 for i in etc/tazlito/*.extract; do
2233 [ -f "$i" ] && . $i ../rootcd
2234 done
2235 # Umount and remove temp directory and cd to $TARGET to get stats.
2236 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2237 cd ..
2238 status
2240 newline
2241 separator
2242 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2243 echo "Distro tree : $(pwd)"
2244 echo "Rootfs size : $(du -sh rootfs)"
2245 echo "Rootcd size : $(du -sh rootcd)"
2246 footer
2247 ;;
2250 list-flavors)
2251 # Show available flavors.
2252 list='/etc/tazlito/flavors.list'
2253 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2254 title 'List of flavors'
2255 cat $list
2256 footer
2257 ;;
2260 show-flavor)
2261 # Show flavor descriptions.
2262 set -e
2263 flavor=${2%.flavor}
2264 flv_dir="$(extract_flavor "$flavor")"
2265 desc="$flv_dir/$flavor.desc"
2266 if [ -n "$brief" ]; then
2267 if [ -z "$noheader" ]; then
2268 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2269 separator
2270 fi
2271 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2272 "$(field ISO "$desc")" \
2273 "$(field Rootfs "$desc")" \
2274 "$(field Description "$desc")"
2275 else
2276 separator
2277 cat "$desc"
2278 fi
2279 cleanup
2280 ;;
2283 gen-liveflavor)
2284 # Generate a new flavor from the live system.
2285 FLAVOR=${2%.flavor}
2286 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2288 case "$FLAVOR" in
2289 -?|-h*|--help)
2290 cat <<EOT
2291 SliTaz Live Tool - Version: $VERSION
2293 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2295 $(boldify '<flavor-patch-file> format:')
2296 $(optlist "\
2297 code data
2298 + package to add
2299 - package to remove
2300 ! non-free package to add
2301 ? display message
2302 @ flavor description
2303 ")
2305 $(boldify 'Example:')
2306 $(optlist "\
2307 @ Developer tools for SliTaz maintainers
2308 + slitaz-toolchain
2309 + mercurial
2310 ")
2311 EOT
2312 exit 1
2313 ;;
2314 esac
2315 mv /etc/tazlito/distro-packages.list \
2316 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2317 rm -f distro-packages.list non-free.list 2>/dev/null
2318 tazpkg recharge
2320 DESC=""
2321 [ -n "$3" ] && \
2322 while read action pkg; do
2323 case "$action" in
2324 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2325 -) yes | tazpkg remove $pkg ;;
2326 !) echo $pkg >> non-free.list ;;
2327 @) DESC="$pkg" ;;
2328 \?) echo -en "$pkg"; read action ;;
2329 esac
2330 done < $3
2332 yes '' | tazlito gen-distro
2333 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2334 mv /etc/tazlito/distro-packages.list.$$ \
2335 /etc/tazlito/distro-packages.list 2>/dev/null
2336 ;;
2339 gen-flavor)
2340 # Generate a new flavor from the last ISO image generated
2341 FLAVOR=${2%.flavor}
2342 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2344 title 'Flavor generation'
2345 check_rootfs
2346 FILES="$FLAVOR.pkglist"
2348 action 'Creating file %s...' "$FLAVOR.flavor"
2349 for i in rootcd rootfs; do
2350 if [ -d "$ADDFILES/$i" ] ; then
2351 FILES="$FILES\n$FLAVOR.$i"
2352 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2353 fi
2354 done
2355 status
2357 answer=$(grep -s ^Description $FLAVOR.desc)
2358 answer=${answer#Description : }
2359 if [ -z "$answer" ]; then
2360 echo -n "Description: "
2361 read answer
2362 fi
2364 action 'Compressing flavor %s...' "$FLAVOR"
2365 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2366 echo "Description : $answer" >> $FLAVOR.desc
2367 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2368 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2369 for i in $(ls $ROOTFS$INSTALLED); do
2370 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2371 EXTRAVERSION=""
2372 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2373 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2374 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2375 echo "$i" >> $FLAVOR.nonfree
2376 else
2377 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2378 fi
2379 done
2380 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2381 for i in $LOCALSTATE/undigest/*/mirror ; do
2382 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2383 done
2384 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2385 touch -t 197001010100.00 $FLAVOR.*
2386 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2387 rm $(echo -e $FILES)
2388 status
2390 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2391 ;;
2394 upgrade-flavor)
2395 # Strip versions from pkglist and update estimated numbers in flavor.desc
2396 flavor="${2%.flavor}"
2397 set -e
2398 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2399 set +e
2401 flv_dir="$(extract_flavor "$flavor")"
2403 strip_versions "$flv_dir/$flavor.pkglist"
2405 action 'Updating %s...' "$flavor.desc"
2407 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2408 set -- $(module calc_sizes "$flv_dir" "$flavor")
2409 restore_mirrors >/dev/null
2411 sed -i -e '/Image is ready/d' \
2412 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2413 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2414 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2415 -e "s|\(Packages *:\).*$|\1 $4|" \
2416 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2417 "$flv_dir/$flavor.desc"
2419 pack_flavor "$flv_dir" "$flavor"
2420 status
2421 display_unknown "$flv_dir/err"
2422 display_warn "$flv_dir/warn"
2423 cleanup
2424 ;;
2427 extract-flavor)
2428 # Extract a flavor into $FLAVORS_REPOSITORY
2429 flavor="${2%.flavor}"
2430 set -e
2431 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2432 set +e
2434 action 'Extracting %s...' "$flavor.flavor"
2435 flv_dir="$(extract_flavor "$flavor" full)"
2436 storage="$FLAVORS_REPOSITORY/$flavor"
2438 rm -rf "$storage" 2>/dev/null
2439 mkdir -p "$storage"
2440 cp -a "$flv_dir"/* "$storage"
2441 rm "$storage/description"
2442 status
2444 strip_versions "$storage/packages.list"
2446 cleanup
2447 ;;
2450 pack-flavor)
2451 # Create a flavor from $FLAVORS_REPOSITORY.
2452 flavor=${2%.flavor}
2453 storage="$FLAVORS_REPOSITORY/$flavor"
2455 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2457 action 'Creating flavor %s...' "$flavor"
2458 tmp_dir="$(mktemp -d)"
2460 while read from to; do
2461 [ -s "$storage/$from" ] || continue
2462 cp -a "$storage/$from" "$tmp_dir/$to"
2463 done <<EOT
2464 mirrors $flavor.mirrors
2465 distro.sh $flavor-distro.sh
2466 receipt $flavor.receipt
2467 non-free.list $flavor.nonfree
2468 EOT
2470 # Build the package list.
2471 # It can include a list from another flavor with the keyword @include
2472 if [ -s "$storage/packages.list" ]; then
2473 include=$(grep '^@include' "$storage/packages.list")
2474 if [ -n "$include" ]; then
2475 include=${include#@include }
2476 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2477 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2478 else
2479 echo -e "\nERROR: Can't find include package list from $include\n"
2480 fi
2481 fi
2482 # Generate the final/initial package list
2483 [ -s "$storage/packages.list" ] && \
2484 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2485 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2486 fi
2488 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2489 # Process multi-rootfs flavor
2490 . "$storage/receipt"
2491 set -- $ROOTFS_SELECTION
2492 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2493 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2494 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2496 for i in rootcd rootfs; do
2497 mkdir "$tmp_dir/$i"
2498 # Copy extra files from the first flavor
2499 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2500 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2501 # Overload extra files by meta flavor
2502 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2503 [ -n "$(ls $tmp_dir/$i)" ] &&
2504 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2505 dogzip "$tmp_dir/$flavor.$i"
2506 rm -rf "$tmp_dir/$i"
2507 done
2508 else
2509 # Process plain flavor
2510 for i in rootcd rootfs; do
2511 [ -d "$storage/$i" ] || continue
2512 (cd "$storage/$i";
2513 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2514 done
2515 fi
2517 unset VERSION MAINTAINER ROOTFS_SELECTION
2518 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2519 ROOTFS_SIZE="$1 (estimated)"
2520 INITRAMFS_SIZE="$2 (estimated)"
2521 ISO_SIZE="$3 (estimated)"
2522 PKGNUM="$4"
2523 . "$storage/receipt"
2525 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2526 Flavor : $FLAVOR
2527 Description : $SHORT_DESC
2528 Version : $VERSION
2529 Maintainer : $MAINTAINER
2530 LiveCD RAM size : $FRUGAL_RAM
2531 Rootfs list : $ROOTFS_SELECTION
2532 Build date : $(date '+%Y%m%d at %T')
2533 Packages : $PKGNUM
2534 Rootfs size : $ROOTFS_SIZE
2535 Initramfs size : $INITRAMFS_SIZE
2536 ISO image size : $ISO_SIZE
2537 ================================================================================
2539 EOT
2541 rm -f $tmp_dir/packages.list
2542 pack_flavor "$tmp_dir" "$flavor"
2543 status
2544 display_unknown "$tmp_dir/err"
2545 display_warn "$flv_dir/warn"
2546 cleanup
2547 ;;
2550 get-flavor)
2551 # Get a flavor's files and prepare for gen-distro.
2552 flavor=${2%.flavor}
2553 title 'Preparing %s distro flavor' "$flavor"
2554 set -e
2555 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2556 set +e
2558 action 'Cleaning %s...' "$DISTRO"
2559 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2560 # Clean old files
2561 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2562 [ -f "$i" ] && rm "$i"
2563 done
2564 mkdir -p "$DISTRO"
2565 status
2567 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2569 action 'Extracting flavor %s...' "$flavor.flavor"
2570 flv_dir="$(extract_flavor "$flavor" info)"
2571 cp -a "$flv_dir"/* .
2572 mv packages.list distro-packages.list
2573 mv -f info /etc/tazlito
2574 status
2576 for i in rootcd rootfs; do
2577 if [ -d "$i" ]; then
2578 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2579 fi
2580 done
2582 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2583 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2585 action 'Updating %s...' 'tazlito.conf'
2586 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2587 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2588 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2589 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2590 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2591 status
2593 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2594 cleanup
2595 ;;
2598 iso2flavor)
2599 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2600 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2602 FLAVOR=${3%.flavor}
2603 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2604 mount -o loop,ro $2 $TMP_DIR/iso
2605 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2606 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2607 ! -s $TMP_DIR/flavor/*.desc ]; then
2608 _ 'META flavors are not supported.'
2609 umount -d $TMP_DIR/iso
2610 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2611 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2612 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2613 umount -d $TMP_DIR/iso
2614 else
2615 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2616 uncompress $i | \
2617 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2618 done
2619 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2620 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2621 '/etc/slitaz-release' '/boot/rootfs.gz'
2622 umount -d $TMP_DIR/iso
2623 else
2624 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2625 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2626 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2627 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2628 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2629 umount -d $TMP_DIR/iso
2630 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2631 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2632 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2633 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2634 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2635 < $TMP_DIR/rootfs$INSTALLED.md5
2636 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2637 if [ -s $TMP_DIR/flavor/*desc ]; then
2638 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2639 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2640 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2641 for i in rootfs rootcd ; do
2642 [ -s $TMP_DIR/flavor/*.list$i ] &&
2643 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2644 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2645 done
2646 else
2647 find_flavor_rootfs $TMP_DIR/rootfs
2648 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2649 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2650 for i in rootfs rootcd ; do
2651 [ "$(ls $TMP_DIR/$i)" ] &&
2652 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2653 done
2654 unset VERSION MAINTAINER
2655 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2656 if [ -n "$DESCRIPTION" ]; then
2657 _n 'Flavor version : '; read -t 30 VERSION
2658 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2659 fi
2661 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2662 Flavor : $FLAVOR
2663 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2664 Version : ${VERSION:-1.0}
2665 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2666 LiveCD RAM size : $RAM_SIZE
2667 Build date : $BUILD_DATE
2668 Packages : $PKGCNT
2669 Rootfs size : $ROOTFS_SIZE
2670 Initramfs size : $INITRAMFS_SIZE
2671 ISO image size : $ISO_SIZE
2672 ================================================================================
2674 EOT
2675 longline "Tazlito can't detect each file installed during \
2676 a package post_install. You should extract this flavor (tazlito extract-flavor \
2677 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2678 tree and remove files generated by post_installs.
2679 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2680 repack the flavor (tazlito pack-flavor $FLAVOR)"
2681 fi
2682 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2683 fi
2684 fi
2685 rm -rf $TMP_DIR
2686 ;;
2689 gen-distro)
2690 # Generate a live distro tree with a set of packages.
2692 check_root
2693 start_time=$(date +%s)
2695 # Tazlito options: --iso or --cdrom
2696 CDROM=''
2697 [ -n "$iso" ] && CDROM="-o loop $iso"
2698 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2700 # Check if a package list was specified on cmdline.
2701 if [ -f "$2" ]; then
2702 LIST_NAME="$2"
2703 else
2704 LIST_NAME='distro-packages.list'
2705 fi
2707 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2708 'Please clean the distro tree or change directory path.'
2709 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2710 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2712 # If list not given: build list with all installed packages
2713 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2714 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2715 fi
2717 # Exit if no list name.
2718 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2720 # Start generation.
2721 title 'Tazlito generating a distro'
2723 # Misc checks
2724 mkdir -p "$PACKAGES_REPOSITORY"
2725 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2726 newline
2728 # Mount CD-ROM to be able to repack boot-loader packages
2729 if [ ! -e /boot -a -n "$CDROM" ]; then
2730 mkdir $TMP_MNT
2731 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2732 ln -s "$TMP_MNT/boot" /
2733 if [ ! -d "$ADDFILES/rootcd" ] ; then
2734 mkdir -p "$ADDFILES/rootcd"
2735 for i in $(ls $TMP_MNT); do
2736 [ "$i" = 'boot' ] && continue
2737 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2738 done
2739 fi
2740 else
2741 rmdir "$TMP_MNT"
2742 fi
2743 fi
2745 # Rootfs stuff.
2746 echo 'Preparing the rootfs directory...'
2747 mkdir -p "$ROOTFS"
2748 export root="$ROOTFS"
2749 # pass current 'mirror' to the root
2750 mkdir -p $root/var/lib/tazpkg $root/etc
2751 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2752 cp -f /etc/slitaz-release $root/etc/slitaz-release
2753 strip_versions "$LIST_NAME"
2755 if [ "$REPACK" = 'y' ]; then
2756 # Determine full packages list with all dependencies
2757 tmp_dir="$(mktemp -d)"
2758 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2759 touch "$tmp_dir/full.pkglist"
2760 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2762 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2763 while read pkgname pkgver; do
2764 # Is package in full list?
2765 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2766 # Is package already repacked?
2767 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2768 _ 'Repacking %s...' "$pkgname-$pkgver"
2769 tazpkg repack "$pkgname" --quiet
2770 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2771 status
2772 done
2774 rm -r "$tmp_dir"
2775 fi
2777 if [ -f non-free.list ]; then
2778 # FIXME: working in the ROOTFS chroot?
2779 newline
2780 echo 'Preparing non-free packages...'
2781 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2782 for pkg in $(cat 'non-free.list'); do
2783 if [ ! -d "$INSTALLED/$pkg" ]; then
2784 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2785 tazpkg get-install get-$pkg
2786 fi
2787 get-$pkg "$ROOTFS"
2788 fi
2789 tazpkg repack $pkg
2790 pkg=$(ls $pkg*.tazpkg)
2791 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2792 mv $pkg $PACKAGES_REPOSITORY
2793 done
2794 fi
2795 cp $LIST_NAME $DISTRO/distro-packages.list
2796 newline
2798 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2800 cd $DISTRO
2801 cp distro-packages.list $ROOTFS/etc/tazlito
2802 # Copy all files from $ADDFILES/rootfs to the rootfs.
2803 if [ -d "$ADDFILES/rootfs" ] ; then
2804 action 'Copying addfiles content to the rootfs...'
2805 cp -a $ADDFILES/rootfs/* $ROOTFS
2806 status
2807 fi
2809 action 'Root filesystem is generated...'; status
2811 # Root CD part.
2812 action 'Preparing the rootcd directory...'
2813 mkdir -p $ROOTCD
2814 status
2816 # Move the boot dir with the Linux kernel from rootfs.
2817 # The efi & boot dirs go directly on the CD.
2818 if [ -d "$ROOTFS/efi" ] ; then
2819 action 'Moving the efi directory...'
2820 mv $ROOTFS/efi $ROOTCD
2821 status
2822 fi
2823 if [ -d "$ROOTFS/boot" ] ; then
2824 action 'Moving the boot directory...'
2825 mv $ROOTFS/boot $ROOTCD
2826 status
2827 fi
2828 cd $DISTRO
2829 # Copy all files from $ADDFILES/rootcd to the rootcd.
2830 if [ -d "$ADDFILES/rootcd" ] ; then
2831 action 'Copying addfiles content to the rootcd...'
2832 cp -a $ADDFILES/rootcd/* $ROOTCD
2833 status
2834 fi
2835 # Execute the distro script used to perform tasks in the rootfs
2836 # before compression. Give rootfs path in arg
2837 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2838 if [ -x "$DISTRO_SCRIPT" ]; then
2839 echo 'Executing distro script...'
2840 sh $DISTRO_SCRIPT $DISTRO
2841 fi
2843 # Execute the custom_rules() found in receipt.
2844 if [ -s "$TOP_DIR/receipt" ]; then
2845 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2846 echo -e "Executing: custom_rules()\n"
2847 . "$TOP_DIR/receipt"
2848 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2849 fi
2850 fi
2852 # Multi-rootfs
2853 if [ -s /etc/tazlito/rootfs.list ]; then
2855 FLAVOR_LIST="$(awk '{
2856 for (i = 2; i <= NF; i+=2)
2857 printf "%s ", $i;
2858 }' /etc/tazlito/rootfs.list)"
2860 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2861 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2862 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2864 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2865 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2866 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2867 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2869 n=0
2870 last=$ROOTFS
2871 while read flavor; do
2872 n=$(($n+1))
2873 mkdir ${ROOTFS}0$n
2874 export root="${ROOTFS}0$n"
2875 # initial tazpkg setup in empty rootfs
2876 tazpkg --root=$root >/dev/null 2>&1
2878 newline
2879 boldify "Building $flavor rootfs..."
2881 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2882 cp "$TOP_DIR/$flavor.flavor" .
2884 if [ ! -s "$flavor.flavor" ]; then
2885 # We may have it in $FLAVORS_REPOSITORY
2886 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2887 tazlito pack-flavor $flavor
2888 else
2889 download $flavor.flavor
2890 fi
2891 fi
2893 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2894 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2895 cp $flavor.pkglist $DISTRO/list-packages0$n
2896 status
2898 strip_versions "$DISTRO/list-packages0$n"
2900 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2902 action 'Updating the boot directory...'
2903 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2904 rm -rf ${ROOTFS}0$n/boot
2906 cd $DISTRO
2907 if [ -s $flavor.rootfs ]; then
2908 _n 'Adding %s rootfs extra files...' "$flavor"
2909 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2910 fi
2912 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2913 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2914 status
2916 rm -f $flavor.flavor install-list
2917 mergefs ${ROOTFS}0$n $last
2918 last=${ROOTFS}0$n
2919 done <<EOT
2920 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2921 EOT
2922 #'
2923 i=$(($n+1))
2924 while [ $n -gt 0 ]; do
2925 mv ${ROOTFS}0$n ${ROOTFS}$i
2926 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2927 gen_initramfs ${ROOTFS}$i
2928 n=$(($n-1))
2929 i=$(($i-1))
2930 export LZMA_HISTORY_BITS=26
2931 done
2932 mv $ROOTFS ${ROOTFS}$i
2933 gen_initramfs ${ROOTFS}$i
2934 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2935 ROOTFS=${ROOTFS}1
2936 else
2937 # Initramfs and ISO image stuff.
2938 gen_initramfs $ROOTFS
2939 fi
2940 gen_livecd_isolinux
2941 distro_stats
2942 cleanup
2943 ;;
2946 clean-distro)
2947 # Remove old distro tree.
2949 check_root
2950 title 'Cleaning: %s' "$DISTRO"
2951 if [ -d "$DISTRO" ] ; then
2952 if [ -d "$ROOTFS" ] ; then
2953 action 'Removing the rootfs...'
2954 rm -f $DISTRO/$INITRAMFS
2955 rm -rf $ROOTFS
2956 status
2957 fi
2958 if [ -d "$ROOTCD" ] ; then
2959 action 'Removing the rootcd...'
2960 rm -rf $ROOTCD
2961 status
2962 fi
2963 action 'Removing eventual ISO image...'
2964 rm -f $DISTRO/$ISO_NAME.iso
2965 rm -f $DISTRO/$ISO_NAME.md5
2966 status
2967 fi
2968 footer
2969 ;;
2972 check-distro)
2973 # Check for a few LiveCD needed files not installed by packages.
2975 # TODO: Remove this function.
2976 # First two files are maintained by tazpkg while it runs on rootfs,
2977 # while last one file should be maintained by tazlito itself.
2978 check_rootfs
2979 title 'Checking distro: %s' "$ROOTFS"
2980 # SliTaz release info.
2981 rel='/etc/slitaz-release'
2982 if [ ! -f "$ROOTFS$rel" ]; then
2983 _ 'Missing release info: %s' "$rel"
2984 else
2985 action 'Release : %s' "$(cat $ROOTFS$rel)"
2986 status
2987 fi
2988 # Tazpkg mirror.
2989 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2990 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2991 todomsg
2992 else
2993 action 'Mirror configuration exists...'
2994 status
2995 fi
2996 # Isolinux msg
2997 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2998 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2999 todomsg
3000 else
3001 action 'Isolinux message seems good...'
3002 status
3003 fi
3004 footer
3005 ;;
3008 writeiso)
3009 # Writefs to ISO image including /home unlike gen-distro we don't use
3010 # packages to generate a rootfs, we build a compressed rootfs with all
3011 # the current filesystem similar to 'tazusb writefs'.
3013 DISTRO='/home/slitaz/distro'
3014 ROOTCD="$DISTRO/rootcd"
3015 COMPRESSION="${2:-none}"
3016 ISO_NAME="${3:-slitaz}"
3017 check_root
3018 # Start info
3019 title 'Write filesystem to ISO'
3020 longline "The command writeiso will write the current filesystem into a \
3021 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3022 newline
3023 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3025 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3026 # Save some space
3027 rm -rf /var/cache/tazpkg/*
3028 rm -f /var/lib/tazpkg/*.bak
3029 rm -rf $DISTRO
3031 # Optionally remove sound card selection and screen resolution.
3032 if [ -z $LaunchedByTazpanel ]; then
3033 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3034 case $anser in
3035 y)
3036 action 'Removing current sound card and screen configurations...'
3037 rm -f /var/lib/sound-card-driver
3038 rm -f /var/lib/alsa/asound.state
3039 rm -f /etc/X11/xorg.conf ;;
3040 *)
3041 action 'Keeping current sound card and screen configurations...' ;;
3042 esac
3043 status
3044 newline
3046 # Optionally remove i18n settings
3047 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3048 case $anser in
3049 y)
3050 action 'Removing current locale/keymap settings...'
3051 newline > /etc/locale.conf
3052 newline > /etc/keymap.conf ;;
3053 *)
3054 action 'Keeping current locale/keymap settings...' ;;
3055 esac
3056 status
3057 fi
3059 # Clean-up files by default
3060 newline > /etc/udev/rules.d/70-persistent-net.rules
3061 newline > /etc/udev/rules.d/70-persistant-cd.rules
3063 # Create list of files including default user files since it is defined in /etc/passwd
3064 # and some new users might have been added.
3065 cd /
3066 echo 'init' > /tmp/list
3067 for dir in bin etc sbin var dev lib root usr home opt; do
3068 [ -d $dir ] && find $dir
3069 done >> /tmp/list
3071 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3072 [ -d $dir ] && echo $dir
3073 done >> /tmp/list
3075 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3077 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3078 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3079 #fi
3080 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3081 touch /var/log/wtmp
3083 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3084 sed -i "/var\/log\/$removelog/d" /tmp/list
3085 done
3087 # Generate initramfs with specified compression and display rootfs
3088 # size in realtime.
3089 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3091 write_initramfs &
3092 sleep 2
3093 cd - > /dev/null
3094 echo -en "\nFilesystem size:"
3095 while [ ! -f /tmp/rootfs ]; do
3096 sleep 1
3097 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3098 done
3099 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3100 echo -e "\n"
3101 rm -f /tmp/rootfs
3103 # Move freshly generated rootfs to the cdrom.
3104 mkdir -p $ROOTCD/boot
3105 mv -f /$INITRAMFS $ROOTCD/boot
3106 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3108 # Now we need the kernel and isolinux files.
3109 copy_from_cd() {
3110 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3111 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3112 unmeta_boot $ROOTCD
3113 umount /media/cdrom
3116 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3117 copy_from_cd;
3118 elif mount | grep /media/cdrom; then
3119 copy_from_cd;
3120 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3121 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3122 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3123 else
3124 touch /tmp/.write-iso-error
3125 longline "When SliTaz is running in RAM the kernel and bootloader \
3126 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3127 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3128 echo -en "----\nENTER to continue..."; read i
3129 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3130 copy_from_cd
3131 fi
3133 # Generate the iso image.
3134 touch /tmp/.write-iso
3135 newline
3136 cd $DISTRO
3137 create_iso $ISO_NAME.iso $ROOTCD
3138 action 'Creating the ISO md5sum...'
3139 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3140 status
3142 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3143 rm -f /tmp/.write-iso
3145 if [ -z $LaunchedByTazpanel ]; then
3146 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3147 case $anser in
3148 y)
3149 umount /dev/cdrom 2>/dev/null
3150 eject
3151 echo -n "Please insert a blank CD-ROM and press ENTER..."
3152 read i && sleep 2
3153 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3154 echo -en "----\nENTER to continue..."; read i ;;
3155 *)
3156 exit 0 ;;
3157 esac
3158 fi
3159 ;;
3162 burn-iso)
3163 # Guess CD-ROM device, ask user and burn the ISO.
3165 check_root
3166 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3167 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3168 # We can specify an alternative ISO from the cmdline.
3169 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3170 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3172 title 'Tazlito burn ISO'
3173 echo "CD-ROM device : /dev/$DRIVE_NAME"
3174 echo "Drive speed : $DRIVE_SPEED"
3175 echo "ISO image : $iso"
3176 footer
3178 case $(yesorno 'Burn ISO image?' 'n') in
3179 y)
3180 title 'Starting Wodim to burn the ISO...'
3181 sleep 2
3182 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3183 footer 'ISO image is burned to CD-ROM.'
3184 ;;
3185 *)
3186 die 'Exiting. No ISO burned.'
3187 ;;
3188 esac
3189 ;;
3192 merge)
3193 # Merge multiple rootfs into one iso.
3195 if [ -z "$2" ]; then
3196 cat <<EOT
3197 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3199 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3200 i.e: rootfsN is a subset of rootfsN-1
3201 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3202 The boot loader will select the rootfs according to the RAM size detected.
3204 Example:
3205 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3207 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3208 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3210 EOT
3211 exit 2
3212 fi
3214 shift # skip merge
3215 append="$1 slitaz1"
3216 shift # skip size1
3217 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3219 ISO=$1.merged
3221 # Extract filesystems
3222 action 'Mounting %s' "$1"
3223 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3224 status || cleanup_merge
3226 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3227 make_bzImage_hardlink $TMP_DIR/iso/boot
3228 umount -d $TMP_DIR/mnt
3229 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3230 _ '%s is already a merged iso. Aborting.' "$1"
3231 cleanup_merge
3232 fi
3233 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3234 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3235 if [ ! -f /boot/isolinux/ifmem.c32 -a
3236 ! -f /boot/isolinux/c32box.c32 ]; then
3237 cat <<EOT
3238 No file /boot/isolinux/ifmem.c32
3239 Please install syslinux package !
3240 EOT
3241 rm -rf $TMP_DIR
3242 exit 1
3243 fi
3244 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3245 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3246 fi
3248 action 'Extracting %s' 'iso/rootfs.gz'
3249 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3250 [ -d $TMP_DIR/rootfs1/etc ]
3251 status || cleanup_merge
3253 n=1
3254 while [ -n "$2" ]; do
3255 shift # skip rootfs N-1
3256 p=$n
3257 n=$(($n + 1))
3258 append="$append $1 slitaz$n"
3259 shift # skip size N
3260 mkdir -p $TMP_DIR/rootfs$n
3262 action 'Extracting %s' "$1"
3263 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3264 [ -d "$TMP_DIR/rootfs$n/etc" ]
3265 status || cleanup_merge
3267 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3268 action 'Creating %s' "rootfs$p.gz"
3269 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3270 status
3271 done
3272 action 'Creating %s' "rootfs$n.gz"
3273 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3274 status
3275 rm -f $TMP_DIR/iso/boot/rootfs.gz
3276 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3277 create_iso $ISO $TMP_DIR/iso
3278 rm -rf $TMP_DIR
3279 ;;
3282 repack)
3283 # Repack an iso with maximum lzma compression ratio.
3285 ISO=$2
3286 mkdir -p $TMP_DIR/mnt
3288 # Extract filesystems
3289 action 'Mounting %s' "$ISO"
3290 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3291 status || cleanup_merge
3293 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3294 umount -d $TMP_DIR/mnt
3296 for i in $TMP_DIR/iso/boot/rootfs* ; do
3297 action 'Repacking %s' "$(basename $i)"
3298 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3299 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3300 align_to_32bits $i
3301 status
3302 done
3304 create_iso $ISO $TMP_DIR/iso
3305 rm -rf $TMP_DIR
3306 ;;
3309 build-loram)
3310 # Build a Live CD for low RAM systems.
3312 ISO="$2"
3313 OUTPUT="$3"
3314 [ -z "$3" ] && \
3315 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3316 mkdir -p "$TMP_DIR/iso"
3317 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3318 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3319 if ! check_iso_for_loram ; then
3320 umount -d "$TMP_DIR/iso"
3321 die "$ISO is not a valid SliTaz live CD. Abort."
3322 fi
3323 case "$4" in
3324 cdrom) build_loram_cdrom ;;
3325 http) build_loram_http ;;
3326 *) build_loram_ram "$5" ;;
3327 esac
3328 umount $TMP_DIR/iso # no -d: needs /proc
3329 losetup -d $loopdev
3330 rm -rf $TMP_DIR
3331 ;;
3334 emu-iso)
3335 # Emulate an ISO image with Qemu.
3336 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3337 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3338 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3339 echo -e "\nStarting Qemu emulator:\n"
3340 echo -e "qemu $QEMU_OPTS $iso\n"
3341 qemu $QEMU_OPTS $iso
3342 ;;
3345 deduplicate)
3346 # Deduplicate files in a tree
3347 shift
3348 deduplicate "$@"
3349 ;;
3352 usage|*)
3353 # Print usage also for all unknown commands.
3354 usage
3355 ;;
3356 esac
3358 exit 0