tazlito view tazlito @ rev 513

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