tazlito view tazlito @ rev 536

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