tazlito view tazlito @ rev 517

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