tazlito view tazlito @ rev 534

busybox cp may not support -n
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Feb 27 21:14:03 2022 +0000 (2022-02-27)
parents 00aa3fa52e4f
children c21a51aa8613
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
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 ] && n=65535 && echo "Warning: truncate EFI eltorito boot file"
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 {
337 if (skiphead!=0) {
338 if ($1=="*") skiphead--
339 next
340 }
341 if (skipdot!=0) {
342 if (skipdot==2) up[cur]=$13 $12
343 else cur=$13 $12
344 skipdot=0
345 next
346 }
347 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
348 if ($3=="2e") skipdot=2
349 else skipdot=1
350 next
351 }
352 if (gotname!=0) {
353 path=""
354 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
355 if (gotname==2) dir[$13 $12]=name
356 else print $1 " " $13 $12 " " path name
357 gotname=0
358 name=""
359 next
360 }
361 if (s!="") {
362 if (eos==0)
363 for (i=2;i<18;i+=2) {
364 if (i==12) i+=2
365 if ($i=="00") break
366 s=s substr($0,i+60,1)
367 }
368 name=s name
369 s=""
370 eos=0
371 next
372 }
373 if ($13=="0f") {
374 s=""
375 for (i=3;i<16;i+=2) {
376 if (i==13) i+=3
377 if ($i=="00") { eos=1; break }
378 s=s substr($0,i+60,1)
379 }
380 next
381 }
382 if ($13=="10") {
383 name=name "/"
384 gotname=2
385 next
386 }
387 if ($13=="20") {
388 gotname=1
389 next
390 }
391 }
392 ' | ( while read offset cluster file; do
393 cluster=$(($(first_block "$2/$file")-basecluster))
394 set32 $((efiblock*2048+0x$offset+10)) $cluster "$1" 16
395 set32 $((efiblock*2048+0x$offset+4)) $((cluster>>16)) "$1" 16
396 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
397 done
399 # Update fat12 or fat16
400 get 57 "$2/$efi_img"
401 dd if="$2/$efi_img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
402 od -An -t u1 -w1 -v
403 ) | awk '
404 {
405 if (state==0) {
406 if ($2=="") {
407 if ($1==12849) fat=12
408 else if ($1==13873) fat=16
409 else fat=32
410 state++
411 }
412 else {
413 for (i=1;i<$2;i++) c[$1+i]=$1+i
414 c[$1+$2]=268435455
415 }
416 next
417 }
418 if (state==1) {
419 prev=$1
420 state++
421 next
422 }
423 if (state==2) {
424 if (fat==12) {
425 n=($1%16)*256+prev
426 if (n!=0) c[pos+1]=n
427 pos++
428 prev=int($1/16)
429 state++
430 next
431 }
432 n=$1*256+prev
433 if (fat==32) {
434 prev=n
435 state=13
436 next
437 }
438 }
439 else if (state==3) {
440 n=$1*16+prev
441 }
442 else if (state==13) {
443 prev=$1*65536+prev
444 state++
445 next
446 }
447 else n=$1*16777216+prev
448 if (n!=0) c[pos+1]=n
449 pos++
450 state=1
451 }
452 END {
453 for (i=1;i<=pos;i+=2) {
454 if (c[i]=="") c[i]=0
455 if (c[i+1]=="") c[i+1]=0
456 if (fat==12) printf "0 %02X %1X%1X %02X |\n",c[i]%256,c[i+1]%16,(c[i]/256)%16,(c[i+1]/16)%256
457 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
458 else {
459 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
460 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
461 }
462 }
463 }' | hexdump_R | dd of="$1" seek=$((4*efiblock+fatsz+resv)) \
464 conv=notrunc bs=512 > /dev/null 2>&1
465 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*efiblock+fatsz+resv)) \
466 count=$fatsz seek=$((4*efiblock+resv)) > /dev/null 2>&1
468 # Cleanup cache
469 umount $2
470 mount -o loop,ro $1 $2
471 }
474 # allocate efi.img stub to share EFI files in the EFI boot partition
476 alloc_uefi_part() {
477 local basedir=$(dirname "$1")/..
478 if [ -s $basedir/$efi_img ]; then
479 chmod +x $basedir/$efi_img
480 return
481 fi
482 local fclust=$({
483 [ -d $basedir/efi ] &&
484 find $basedir/efi -type f -exec busybox stat -c "%s %n" {} \;
485 while [ -s "$1" ]; do
486 local efifile
487 case "$1" in
488 *taz) efifile=bootia32.efi ;;
489 *taz64) efifile=bootx64.efi ;;
490 esac
491 if [ ! -s $basedir/efi/boot/$efifile ] &&
492 [ $(get $((0x82)) "$1") = $((0x4550)) ]; then
493 mkdir -p $basedir/efi/boot 2> /dev/null
494 ln "$1" "$basedir/efi/boot/$efifile"
495 stat -c "%s %n" "$1"
496 for i in $basedir/boot/rootfs* ; do
497 ln "$i" $basedir/efi/boot/ &&
498 stat -c "%s %n" "$i"
499 done 2> /dev/null
500 [ -s $basedir/efi/boot/linux.cmdline ] ||
501 sed 's|/|\\|g' > $basedir/efi/boot/linux.cmdline <<EOT
502 rw root=0x100$(sed '/bzImage/!d;s|.*root=[^ ]*||;q' $basedir/boot/isolinux/isolinux.cfg)\
503 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
504 echo -n " initrd=/EFI/BOOT/$f";done)
505 EOT
506 fi
507 shift
508 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
509 [ ${fclust:-0} -eq 0 ] && return
510 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
511 BEGIN {
512 FS="/"
513 }
514 NF > 1 {
515 d[NF $NF]+=2
516 d[NF-1 $(NF-1)]+=($NF+25)/13
517 }
518 END {
519 for (i in d)
520 n+=int((d[i]+63)/64)
521 print n
522 }')
523 local clusters=$((fclust+dclust))
524 if [ $clusters -lt 4068 ]; then
525 fsect=$((((clusters+2)*3+1023)/1024))
526 ftype="31 32"
527 fhead="F8 FF FF"
528 rsect=$(( 1+ ((2*fsect)-1)%4 ))
529 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
530 rootsz=2
531 elif [ $clusters -lt 65525 ]; then
532 fsect=$(((clusters+2+255)/256))
533 ftype="31 36"
534 fhead="F8 FF FF FF"
535 rsect=$(( 1+ ((2*fsect)-1)%4 ))
536 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
537 rootsz=2
538 else
539 fsect=$(((clusters+2+127)/128))
540 ftype="33 32"
541 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
542 rsect=$(( 6+ ((2*fsect)-6)%4 ))
543 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
544 rootsz=1
545 fi
546 # reserved + fat*2 + root dir + dirs
547 count=$(((rsect + fsect*2)/4 + rootsz + dclust ))
548 s=$(((count+fclust)*4))
549 if [ $s -gt 65535 ]; then
550 size="00 00"
551 size32="$(printf "%02X %02X %02X %02X" $((s%256)) \
552 $(((s>>8)%256)) $(((s>>16)%256)) $(((s>>24)%256)) )"
553 else
554 size="$(printf "%02X %02X" $((s%256)) $(((s>>8)%256)) )"
555 size32="00 00 00 00"
556 fi
557 dd if=/dev/zero bs=512 of=$basedir/$efi_img \
558 count=$s 2> /dev/null
560 # Create boot sector
561 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
562 if [ "$ftype" = "33 32" ]; then
563 hexdump_R <<EOT | dd of=$basedir/$efi_img \
564 conv=notrunc
565 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
566 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
567 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
568 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
569 0 80 00 29 00 00 00 00 $doslabel |
570 0 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
571 EOT
572 while read ofs data; do
573 echo "0 ${data//:/ } |" | hexdump_R | dd conv=notrunc \
574 bs=1 seek=$ofs of=$basedir/$efi_img
575 done <<EOT
576 510 55:aa:52:52:61:41
577 996 72:72:41:61:ff:ff:ff:ff:02
578 1022 55:aa
579 EOT
580 else
581 echo -en '\x55\xAA' | dd of=$basedir/$efi_img \
582 seek=510 bs=1 conv=notrunc
583 hexdump_R <<EOT | dd of=$basedir/$efi_img \
584 conv=notrunc
585 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
586 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
587 0 $size32 80 00 29 00 00 00 00 $doslabel |
588 0 46 41 54 $ftype 20 20 20 cd 18 |
589 0 cd 19 eb fa |
590 EOT
591 fi 2> /dev/null
593 # Create fats
594 echo "0 $fhead |" | hexdump_R | dd of=$basedir/$efi_img \
595 seek=$((rsect)) bs=512 conv=notrunc 2> /dev/null
596 echo "0 $fhead |" | hexdump_R | dd of=$basedir/$efi_img \
597 seek=$((rsect+fsect)) bs=512 conv=notrunc 2> /dev/null
599 # Add label
600 echo "0 $doslabel 08 |" | hexdump_R | \
601 dd of=$basedir/$efi_img bs=512 conv=notrunc \
602 seek=$((rsect+fsect+fsect)) 2> /dev/null
604 mkdir -p /tmp/mnt$$
605 mount -o loop $basedir/$efi_img /tmp/mnt$$
606 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
607 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
608 sync
609 dd if=$basedir/$efi_img of=/tmp/fat$$ \
610 skip=$rsect bs=512 count=$fsect 2> /dev/null
611 ( cd $basedir; find efi/boot -type f | cpio -o -H newc ) | \
612 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
613 umount /tmp/mnt$$
614 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/$efi_img \
615 seek=$rsect bs=512 conv=notrunc 2> /dev/null
616 rm /tmp/fat$$
617 rmdir /tmp/mnt$$
619 dd count=0 bs=2k of=$basedir/$efi_img \
620 seek=$count 2> /dev/null
621 }
624 # isolinux.conf doesn't know the kernel version.
625 # We name the kernel image 'bzImage'.
626 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
628 make_bzImage_hardlink() {
629 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
630 rm -f ${1:-.}/bzImage 2>/dev/null
631 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
632 fi
633 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
634 rm -f ${1:-.}/bzImage64 2> /dev/null
635 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
636 fi
637 }
640 create_iso() {
641 cd $2
642 deduplicate
643 sed -i "s|20[1-9][0-9]|$(date +%Y)|" $2/README $2/index.html
645 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
646 make_bzImage_hardlink $2/boot
647 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
649 while read file; do ls -r $file 2> /dev/null; done << EOT | \
650 awk 'BEGIN { n=100 } { print $1 " " n-- }' > /tmp/cdsort$$
651 $PWD/boot/isolinux/boot.cat
652 $PWD/boot/isolinux/isolinux.bin
653 $PWD/boot/isolinux/isolinux.cfg
654 $PWD/boot/isolinux/vesamenu.c32
655 $PWD/boot/isolinux/splash.*g
656 $PWD/boot/isolinux/i18n.cfg
657 $PWD/boot/isolinux/c32box.c32
658 $PWD/boot/isolinux/kbd
659 $PWD/$efi_img
660 $PWD/boot/bzImage*
661 $PWD/efi/boot/linux.cmdline*
662 $(ls $PWD/boot/rootfs* | tac)
663 EOT
665 action 'Computing md5...'
666 touch $2/boot/isolinux/boot.cat
667 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
668 sort -k 2 > md5sum
669 status
671 cd - >/dev/null
672 title 'Generating ISO image'
674 _ 'Generating %s' "$1"
675 uefi="$(cd $2 ; ls $efi_img 2> /dev/null)"
676 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
677 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
678 -no-emul-boot -boot-load-size 4 -boot-info-table \
679 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
680 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
681 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
682 -A "tazlito $VERSION/$(genisoimage --version)" \
683 -copyright README -P "www.slitaz.org" -no-pad $2
684 rm -f /tmp/cdsort$$
685 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
687 mkdir /tmp/mnt$$
688 mount -o loop,ro $1 /tmp/mnt$$
689 fixup_uefi_part $1 /tmp/mnt$$
690 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
691 ${uefi:+$efi_img} ; do
692 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
693 done
694 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
695 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
696 umount -d /tmp/mnt$$
697 rmdir /tmp/mnt$$
699 if [ -s '/etc/tazlito/info' ]; then
700 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
701 action 'Storing ISO info...'
702 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
703 status
704 fi
705 fi
707 if [ -x '/usr/bin/isohybrid' ]; then
708 action 'Creating hybrid ISO...'
709 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
710 status
711 fi
713 if [ -x '/usr/bin/iso2exe' ]; then
714 echo 'Creating EXE header...'
715 /usr/bin/iso2exe $1 2>/dev/null
716 fi
717 }
720 # Generate a new ISO image using isolinux.
722 gen_livecd_isolinux() {
723 # Some packages may want to alter iso
724 genisohooks iso
725 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
727 # Set date for boot msg.
728 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
729 DATE=$(date +%Y%m%d)
730 action 'Setting build date to: %s...' "$DATE"
731 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
732 status
733 fi
735 cd $DISTRO
736 create_iso $ISO_NAME.iso $ROOTCD
738 action 'Creating the ISO md5sum...'
739 md5sum $ISO_NAME.iso > $ISO_NAME.md5
740 status
742 separator
743 # Some packages may want to alter final iso
744 genisohooks final
745 }
748 lzma_history_bits() {
749 #
750 # This generates an ISO which boots with Qemu but gives
751 # rootfs errors in frugal or liveUSB mode.
752 #
753 # local n
754 # local sz
755 # n=20 # 1Mb
756 # sz=$(du -sk $1 | cut -f1)
757 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
758 # n=$(( n + 1 ))
759 # sz=$(( sz / 2 ))
760 # done
761 # echo $n
762 echo ${LZMA_HISTORY_BITS:-24}
763 }
766 lzma_switches() {
767 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
768 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
769 }
772 lzma_set_size() {
773 # Update size field for lzma'd file packed using -si switch
774 return # Need to fix kernel code?
776 local n i
777 n=$(unlzma < $1 | wc -c)
778 for i in $(seq 1 8); do
779 printf '\\\\x%02X' $((n & 255))
780 n=$((n >> 8))
781 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
782 }
785 align_to_32bits() {
786 local size=$(stat -c %s ${1:-/dev/null})
787 [ $((${size:-0} & 3)) -ne 0 ] &&
788 dd if=/dev/zero bs=1 count=$((4 - (size & 3))) >> $1 2>/dev/null
789 }
792 dolz4() {
793 [ "$(which lz4)" ] || tazpkg get-install lz4
794 lz4 -9 > $1
795 }
798 dogzip() {
799 gzip -9 > $1
800 [ -x /usr/bin/advdef ] && advdef -qz4 $1
801 }
804 # Pack rootfs
806 pack_rootfs() {
807 ( cd $1; find . -print | cpio -o -H newc ) | \
808 case "$COMPRESSION" in
809 none)
810 _ 'Creating %s without compression...' 'initramfs'
811 cat > $2
812 ;;
813 lz4)
814 _ 'Creating %s with lz4 compression...' 'initramfs'
815 dolz4 $2
816 ;;
817 gzip)
818 _ 'Creating %s with gzip compression...' 'initramfs'
819 dogzip $2
820 ;;
821 *)
822 _ 'Creating %s with lzma compression...' 'initramfs'
823 lzma e -si -so $(lzma_switches $1) > $2
824 lzma_set_size $2
825 ;;
826 esac
827 align_to_32bits $2
828 echo 1 > /tmp/rootfs
829 }
832 # Compression functions for writeiso.
834 write_initramfs() {
835 case "$COMPRESSION" in
836 lzma)
837 _n 'Creating %s with lzma compression...' "$INITRAMFS"
838 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
839 align='y'
840 lzma_set_size "/$INITRAMFS"
841 ;;
842 gzip)
843 _ 'Creating %s with gzip compression...' "$INITRAMFS"
844 cpio -o -H newc | dogzip "/$INITRAMFS"
845 ;;
846 lz4)
847 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
848 cpio -o -H newc | dolz4 "/$INITRAMFS"
849 ;;
850 *)
851 # align='y'
852 _ 'Creating %s without compression...' "$INITRAMFS"
853 cpio -o -H newc > "/$INITRAMFS"
854 ;;
855 esac < /tmp/list
856 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
857 echo 1 > /tmp/rootfs
858 }
861 # Deduplicate files (MUST be on the same filesystem).
863 deduplicate() {
864 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec busybox stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
865 (
866 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
867 while read attr inode link file; do
868 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
869 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
870 rm -f "$file"
871 if ln "$old_file" "$file" 2>/dev/null; then
872 hinode="$inode"
873 inode="$old_inode"
874 [ "$link" -eq 1 ] && hardlinks=$((hardlinks+1)) &&
875 save="$((save+(${attr%%-*}+512)/1024))"
876 continue
877 else
878 cp -p "$old_file" "$file"
879 fi
880 else
881 hinode=""
882 fi
883 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
884 done
885 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
886 )
888 find "$@" -xdev -type l -exec busybox stat -c '%s-%u-%g %i %h %n' {} \; | \
889 while read attr inode link file; do
890 echo "$attr-$(readlink "$file" | uuencode -m - | \
891 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
892 done | sort | \
893 (
894 old_attr=""; hardlinks=0;
895 while read attr inode link file; do
896 if [ "$attr" = "$old_attr" ]; then
897 if [ "$inode" != "$old_inode" ]; then
898 rm -f "$file"
899 if ln "$old_file" "$file" 2>/dev/null; then
900 [ "$link" -eq 1 ] && hardlinks=$((hardlinks+1))
901 else
902 cp -a "$old_file" "$file"
903 fi
904 fi
905 else
906 old_file="$file"
907 old_attr="$attr"
908 old_inode="$inode"
909 fi
910 done
911 _ '%s duplicate symlinks.' "$hardlinks"
912 )
913 }
916 # Generate a new initramfs from the root filesystem.
918 gen_initramfs() {
919 # Just in case CTRL+c
920 rm -f $DISTRO/gen
922 # Some packages may want to alter rootfs
923 genisohooks rootfs
924 cd $1
926 # Normalize file time
927 find $1 -newer $1 -exec touch -hr $1 {} \;
929 # Link duplicate files
930 deduplicate
932 # Use lzma if installed. Display rootfs size in realtime.
933 rm -f /tmp/rootfs 2>/dev/null
934 pack_rootfs . $DISTRO/$(basename $1).gz &
935 sleep 2
936 echo -en "\nFilesystem size:"
937 while [ ! -f /tmp/rootfs ]; do
938 sleep 1
939 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
940 done
941 echo -e "\n"
942 rm -f /tmp/rootfs
943 cd $DISTRO
944 mv $(basename $1).gz $ROOTCD/boot
945 }
948 distro_sizes() {
949 if [ -n "$start_time" ]; then
950 time=$(($(date +%s) - start_time))
951 sec=$time
952 div=$(( (time + 30) / 60))
953 [ "$div" -ne 0 ] && min="~ ${div}m"
954 _ 'Build time : %ss %s' "$sec" "$min"
955 fi
956 cat <<EOT
957 Build date : $(date +%Y%m%d)
958 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
959 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
960 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
961 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
962 EOT
963 footer "Image is ready: $ISO_NAME.iso"
964 }
967 # Print ISO and rootfs size.
969 distro_stats() {
970 title 'Distro statistics: %s' "$DISTRO"
971 distro_sizes
972 }
975 # Create an empty configuration file.
977 empty_config_file() {
978 cat >> tazlito.conf <<"EOF"
979 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
980 #
982 # Name of the ISO image to generate.
983 ISO_NAME=""
985 # ISO image volume name.
986 VOLUM_NAME="SliTaz"
988 # Name of the preparer.
989 PREPARED="$USER"
991 # Path to the packages repository and the packages.list.
992 PACKAGES_REPOSITORY=""
994 # Path to the distro tree to gen-distro from a list of packages.
995 DISTRO=""
997 # Path to the directory containing additional files
998 # to copy into the rootfs and rootcd of the LiveCD.
999 ADDFILES="$DISTRO/addfiles"
1001 # Default answer for binary question (Y or N)
1002 DEFAULT_ANSWER="ASK"
1004 # Compression utility (lzma, gzip or none)
1005 COMPRESSION="lzma"
1006 EOF
1010 # Extract rootfs.gz somewhere
1012 extract_rootfs() {
1013 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
1014 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1015 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1016 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1017 (cd "$2"; cpio -idm --quiet 2>/dev/null < "$1")
1021 # Extract flavor file to temp directory
1023 extract_flavor() {
1024 # Input: $1 - flavor name to extract;
1025 # $2 = absent/empty: just extract 'outer layer'
1026 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1027 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1028 # Output: temp dir path where flavor was extracted
1029 local f="$1.flavor" from to infos="$1.desc"
1030 [ -f "$f" ] || die "File '$f' not found"
1031 local dir="$(mktemp -d)"
1032 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1034 if [ -n "$2" ]; then
1035 cd $dir
1037 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1039 for i in rootcd rootfs; do
1040 [ -f "$1.$i" ] || continue
1041 mkdir "$i"
1042 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1043 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1044 rm "$1.$i"
1045 done
1046 touch -t 197001010100.00 $1.*
1047 # Info to be stored inside ISO
1048 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1049 rm $1.list*
1051 # Renames
1052 while read from to; do
1053 [ -f "$from" ] || continue
1054 mv "$from" "$to"
1055 done <<EOT
1056 $1.nonfree non-free.list
1057 $1.pkglist packages.list
1058 $1-distro.sh distro.sh
1059 $1.receipt receipt
1060 $1.mirrors mirrors
1061 $1.desc description
1062 EOT
1063 fi
1065 echo $dir
1069 # Pack flavor file from temp directory
1071 pack_flavor() {
1072 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1076 # Remove duplicate files
1078 files_match() {
1079 if [ -d "$1" ]; then
1080 return 1
1082 elif [ -L "$1" ] && [ -L "$2" ]; then
1083 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1085 elif [ -f "$1" ] && [ -f "$2" ]; then
1086 cmp -s "$1" "$2" && return 0
1088 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1089 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1090 return 0
1092 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1093 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1094 return 0
1096 fi 2> /dev/null
1097 return 1
1100 remove_with_path() {
1101 dir="$(dirname $1)"
1102 rm -f "$1"
1103 while rmdir "$dir" 2> /dev/null; do
1104 dir="$(dirname $dir)"
1105 done
1108 mergefs() {
1109 # Note, many packages have files with spaces in the name
1110 IFS=$'\n'
1112 local size1=$(du -hs "$1" | awk '{ print $1 }')
1113 local size2=$(du -hs "$2" | awk '{ print $1 }')
1114 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1116 # merge symlinks files and devices
1117 ( cd "$1"; find . ) | \
1118 while read file; do
1119 files_match "$1/$file" "$2/$file" "$file" &&
1120 remove_with_path "$2/$file"
1121 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1122 done
1124 unset IFS
1125 status
1129 cleanup_merge() {
1130 rm -rf $TMP_DIR
1131 exit 1
1135 # Update isolinux config files for multiple rootfs
1137 update_bootconfig() {
1138 local files
1139 action 'Updating boot config files...'
1140 files="$(grep -l 'include common' $1/*.cfg)"
1141 for file in $files; do
1142 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1143 if (/label/) label=$0;
1144 else if (/kernel/) kernel=$0;
1145 else if (/append/) {
1146 i=index($0,"rootfs.gz");
1147 append=substr($0,i+9);
1149 else if (/include/) {
1150 for (i = 1; i <= n; i++) {
1151 print label i
1152 print kernel;
1153 initrd="initrd=/boot/rootfs" n ".gz"
1154 for (j = n - 1; j >= i; j--) {
1155 initrd=initrd ",/boot/rootfs" j ".gz";
1157 printf "\tappend %s%s\n",initrd,append;
1158 print "";
1160 print;
1162 else print;
1163 }' < $file > $file.$$
1164 mv -f $file.$$ $file
1165 done
1166 sel="$(echo $2 | awk '{
1167 for (i=1; i<=NF; i++)
1168 if (i % 2 == 0) printf " slitaz%d", i/2
1169 else printf " %s", $i
1170 }')"
1172 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1174 label slitaz
1175 kernel /boot/isolinux/ifmem.c32
1176 append$sel noram
1178 label noram
1179 config noram.cfg
1181 EOT
1183 # Update vesamenu
1184 if [ -s "$1/isolinux.cfg" ]; then
1185 files="$files $1/isolinux.cfg"
1186 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1187 BEGIN {
1188 kernel = " COM32 c32box.c32"
1191 if (/ROWS/) print "MENU ROWS " n+$3;
1192 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1193 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1194 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1195 else if (/VSHIFT/) {
1196 x = $3-n;
1197 if (x < 0) x = 0;
1198 print "MENU VSHIFT " x;
1200 else if (/rootfs.gz/) {
1201 linux = "";
1202 if (/bzImage/) linux = "linux /boot/bzImage ";
1203 i = index($0, "rootfs.gz");
1204 append = substr($0, i+9);
1205 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1206 printf "\tappend%s noram\n", sel;
1207 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1208 for (i = 1; i <= n; i++) {
1209 print "LABEL slitaz" i
1210 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1211 printf "%s\n", kernel;
1212 initrd = "initrd=/boot/rootfs" n ".gz"
1213 for (j = n - 1; j >= i; j--) {
1214 initrd = initrd ",/boot/rootfs" j ".gz";
1216 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1219 else if (/bzImage/) kernel = $0;
1220 else print;
1221 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1222 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1223 fi
1225 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1226 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1227 cat > $1/noram.cfg <<EOT
1228 implicit 0
1229 prompt 1
1230 timeout 80
1231 $(grep '^F[0-9]' $1/isolinux.cfg)
1233 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1234 say Not enough RAM to boot slitaz. Trying hacker mode...
1235 default hacker
1236 label hacker
1237 KERNEL /boot/bzImage
1238 append rw root=/dev/null vga=normal
1240 label reboot
1241 EOT
1243 if [ -s $1/c32box.c32 ]; then
1244 cat >> $1/noram.cfg <<EOT
1245 COM32 c32box.c32
1246 append reboot
1248 label poweroff
1249 COM32 c32box.c32
1250 append poweroff
1252 EOT
1253 else
1254 echo " com32 reboot.c32" >> $1/noram.cfg
1255 fi
1257 # Restore real label names
1258 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1259 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1260 while read pat; do
1261 sed -i "s/slitaz$pat/" $files
1262 done
1263 status
1267 # Uncompress rootfs or module to stdout
1269 uncompress() {
1270 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1271 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1275 # Install a missing package
1277 install_package() {
1278 if [ -z "$2" ]; then
1279 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1280 else
1281 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1282 fi
1283 case "$answer" in
1284 y)
1285 # We don't want package on host cache.
1286 action 'Getting and installing package: %s' "$1"
1287 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1288 status ;;
1289 *)
1290 return 1 ;;
1291 esac
1295 # Check iso for loram transformation
1297 check_iso_for_loram() {
1298 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1299 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1303 # Remove duplicated files in $1/efi/boot from $1/boot
1305 cleanup_efi_boot() {
1306 for i in $1/$efi_img $1/boot/isolinux/efi.img ; do
1307 [ -s $i ] && [ ! -x $i ] && rm -f $i
1308 done
1309 for i in $1/efi/boot/* ; do
1310 [ -f $i ] || continue
1311 case "$i" in
1312 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1313 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1314 rm $1/efi/boot/linux.cmdline ;;
1315 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1316 rm $1/efi/boot/linux.cmdline* ;;
1317 esac
1318 rm -f $i
1319 rmdir $1/efi/boot && rmdir $1/efi
1320 done 2> /dev/null
1324 # Build initial rootfs for loram ISO ram/cdrom/http
1326 build_initfs() {
1327 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1328 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1329 mirror3.slitaz.org mirror.slitaz.org"
1330 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1331 [ -z "$version" ] && die "Can't find the kernel version." \
1332 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1334 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1335 need_lib=false
1336 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1337 mkdir -p $TMP_DIR/initfs/$i
1338 done
1339 ln -s bin $TMP_DIR/initfs/sbin
1340 ln -s . $TMP_DIR/initfs/usr
1341 for aufs in aufs overlayfs; do
1342 for v in $version ; do
1343 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1344 install_package ${v/*taz/linux}-$aufs $v && continue
1345 done
1346 install_package $aufs $version && break
1347 done || return 1
1348 [ -s /init ] || install_package slitaz-boot-scripts
1349 cp /init $TMP_DIR/initfs/
1350 for v in $version ; do
1351 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1352 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1353 done
1354 if [ "$1" = 'cdrom' ]; then
1355 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1356 else
1357 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1358 for v in $version ; do
1359 if [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; then
1360 install_package linux-squashfs $v || return 1
1361 fi
1362 done
1363 for v in $version ; do
1364 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1365 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1366 done
1367 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1368 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1369 fi
1370 if [ "$1" = 'http' ]; then
1371 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1372 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1373 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1374 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1375 cp -a /dev/fuse $TMP_DIR/initfs/dev
1376 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1377 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1378 else
1379 need_lib=true
1380 fi
1381 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1382 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1383 else
1384 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1385 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1386 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1387 cp -a /lib/librt* $TMP_DIR/initfs/lib
1388 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1389 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1390 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1391 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1392 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1393 need_lib=true
1394 fi
1395 cd $TMP_DIR/fs
1396 echo 'Getting slitaz-release & ethernet modules...'
1397 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1398 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1399 [ -s rootfs* ] || continue
1400 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1401 rm -f rootfs*
1402 done 2>&1 > /dev/null
1403 cd - > /dev/null
1404 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1405 for v in $version ; do
1406 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1407 -type f -name '*.ko*' | while read mod; do
1408 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1409 uncompress $mod > $f
1410 grep -q alias=pci: $f || rm -f $f
1411 done
1412 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1413 f=$(basename $i)..z
1414 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1415 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1416 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1417 for j in $deps; do
1418 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1419 uncompress $mod > $(echo $j | sed s/..z$//)
1420 done
1421 done
1422 done
1423 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"
1424 _n 'List of URLs to insert: '
1425 read -t 30 urliso2
1426 urliso="$urliso2 $urliso"
1427 fi
1428 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1429 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1430 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1431 else
1432 cp /bin/busybox $TMP_DIR/initfs/bin
1433 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1434 cp /sbin/insmod $TMP_DIR/initfs/bin
1435 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1436 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1437 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1438 fi
1439 need_lib=true
1440 fi
1441 bins="sh switch_root"
1442 [ "$(echo ls | chroot $TMP_DIR/initfs busybox sh 2> /dev/null)" ] ||
1443 bins="$($TMP_DIR/initfs/bin/busybox | awk \
1444 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g')"
1445 for i in $bins ; do
1446 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1447 done
1448 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1449 for v in $version ; do
1450 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1451 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1452 done
1453 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1454 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1455 cp -a $i $TMP_DIR/initfs/dev
1456 done
1457 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1458 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1459 cp -a $i $TMP_DIR/initfs/dev
1460 done 2>/dev/null
1461 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1462 cp -a $i $TMP_DIR/initfs/lib
1463 done
1464 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1465 #!/bin/sh
1467 getarg() {
1468 grep -q " \$1=" /proc/cmdline || return 1
1469 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1470 return 0
1473 copy_rootfs() {
1474 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1475 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1476 [ \$(( total / need )) -gt 1 ] || return 1
1477 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1478 path=/mnt/
1479 return 0
1480 else
1481 rm -f /mnt/rootfs*
1482 return 1
1483 fi
1486 echo "Switching / to tmpfs..."
1487 mount -t proc proc /proc
1488 size="\$(grep rootfssize= < /proc/cmdline | \\
1489 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1490 [ -n "\$size" ] || size="-o size=90%"
1492 mount -t sysfs sysfs /sys
1493 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1494 [ -s \$i ] && continue
1495 echo -en "Probe \$i \\r"
1496 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1497 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1498 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1499 insmod /lib/modules/\$k.ko 2> /dev/null
1500 done
1501 echo "Loading \$i"
1502 insmod \$i 2> /dev/null
1503 break
1504 done
1505 done
1506 umount /sys
1507 while read var default; do
1508 eval \$var=\$default
1509 getarg \$var \$var
1510 done <<EOT
1511 eth eth0
1512 dns 208.67.222.222,208.67.220.220
1513 netmask 255.255.255.0
1514 gw
1515 ip
1516 EOT
1517 grep -q \$eth /proc/net/dev || sh
1518 if [ -n "\$ip" ]; then
1519 ifconfig \$eth \$ip netmask \$netmask up
1520 route add default gateway \$gw
1521 for i in \$(echo \$dns | sed 's/,/ /g'); do
1522 echo "nameserver \$i" >> /etc/resolv.conf
1523 done
1524 else
1525 udhcpc -f -q -s /lib/udhcpc -i \$eth
1526 fi
1527 for i in $urliso ; do
1528 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1529 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"
1530 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1531 done
1532 getarg urliso URLISO
1533 DIR=fs
1534 if getarg loram DIR; then
1535 DEVICE=\${DIR%,*}
1536 DIR=/\${DIR#*,}
1537 fi
1538 mount -t tmpfs \$size tmpfs /mnt
1539 path2=/mnt/.httpfs/
1540 path=/mnt/.cdrom/
1541 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1542 while [ ! -d \$path/boot ]; do
1543 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1544 httpfs \$i \$path2 && echo \$i && break
1545 done
1546 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1547 done
1549 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1550 umount /proc
1551 branch=:/mnt/.cdrom/\$DIR
1552 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1553 branch=
1554 lp=1
1555 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1556 [ -s \$i ] && insmod \$i
1557 done 2> /dev/null
1558 for i in \${path}boot/rootfs?.* ; do
1559 fs=\${i#*root}
1560 branch=\$branch:/mnt/.\$fs
1561 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1562 losetup -o 124 /dev/loop\$lp \$i
1563 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1564 lp=\$((lp+1))
1565 done
1566 fi
1567 mkdir -p /mnt/.rw/mnt/.httpfs
1568 while read type opt; do
1569 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1570 [ -s \$i ] && insmod \$i &&
1571 mount -t \$type -o \$opt none /mnt && break 2
1572 done
1573 done <<EOT
1574 aufs br=/mnt/.rw\$branch
1575 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1576 EOT
1577 rm -rf /lib/modules
1578 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1579 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1580 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1581 EOTEOT
1582 chmod +x $TMP_DIR/initfs/init
1583 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1584 [ -s $i ] || continue
1585 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1586 rm -f $i
1587 done 2>/dev/null
1588 (cd $TMP_DIR/initfs; find . | busybox cpio -o -H newc 2>/dev/null) | \
1589 lzma e $TMP_DIR/initfs.gz -si
1590 lzma_set_size $TMP_DIR/initfs.gz
1591 rm -rf $TMP_DIR/initfs
1592 align_to_32bits $TMP_DIR/initfs.gz
1593 return 0
1597 # Move each initramfs to squashfs
1599 build_loram_rootfs() {
1600 rootfs_sizes=""
1601 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1602 mkdir -p $TMP_DIR/fs
1603 cd $TMP_DIR/fs
1604 uncompress $i | cpio -idm
1605 deduplicate
1606 cd - > /dev/null
1607 rootfs=$TMP_DIR/$(basename $i 64)
1608 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1609 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1610 cd $TMP_DIR
1611 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1612 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1613 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1614 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1615 rm -f $rootfs
1616 mv ${rootfs%64}.cpio $rootfs
1617 cd - > /dev/null
1618 rm -rf $TMP_DIR/fs
1619 done
1623 # Move meta boot configuration files to basic configuration files
1624 # because meta loram flavor is useless when rootfs is not loaded in RAM
1626 unmeta_boot() {
1627 local root=${1:-$TMP_DIR/loramiso}
1628 if [ -f $root/boot/isolinux/noram.cfg ]; then
1629 # We keep enough information to do unloram...
1630 [ -s $root/boot/isolinux/common.cfg ] &&
1631 sed -i 's/label slitaz/label orgslitaz/' \
1632 $root/boot/isolinux/common.cfg
1633 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1634 shift
1635 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1636 $root/boot/isolinux/isolinux.cfg
1637 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1638 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1639 $root/boot/isolinux/*.cfg
1640 fi
1644 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1645 # These squashfs may be loaded in RAM at boot time.
1646 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1647 # Meta flavors are converted to normal flavors.
1649 build_loram_cdrom() {
1650 build_initfs cdrom || return 1
1651 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1652 cleanup_efi_boot $TMP_DIR/loramiso
1653 mkdir $TMP_DIR/loramiso/fs
1654 cd $TMP_DIR/loramiso/fs
1655 for i in $( ls ../boot/root* | sort -r ) ; do
1656 uncompress $i | cpio -idmu
1657 rm -f $i
1658 done
1659 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1660 cd - >/dev/null
1661 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1662 unmeta_boot
1663 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1664 busybox sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1665 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1666 busybox sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' \
1667 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1668 create_iso $OUTPUT $TMP_DIR/loramiso
1672 # Create http bootstrap to load and remove loram_cdrom
1673 # Meta flavors are converted to normal flavors.
1675 build_loram_http() {
1676 build_initfs http || return 1
1677 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1678 cleanup_efi_boot $TMP_DIR/loramiso
1679 rm -f $TMP_DIR/loramiso/boot/rootfs*
1680 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1681 unmeta_boot
1682 create_iso $OUTPUT $TMP_DIR/loramiso
1686 # Update meta flavor selection sizes.
1687 # Reduce sizes with rootfs gains.
1689 update_metaiso_sizes() {
1690 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1691 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1692 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1693 do
1694 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1695 local sizes="$rootfs_sizes"
1696 local new
1697 set -- $append
1698 shift
1699 [ "$1" = "ifmem" ] && shift
1700 new=""
1701 while [ -n "$2" ]; do
1702 local s
1703 case "$1" in
1704 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1705 *M) s=$(( ${1%M} * 1024 ));;
1706 *) s=${1%K};;
1707 esac
1708 sizes=${sizes#* }
1709 for i in $sizes ; do
1710 s=$(( s - i ))
1711 done
1712 new="$new $s $2"
1713 shift 2
1714 done
1715 busybox sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1716 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1717 busybox sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1718 busybox sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1719 busybox sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' $cfg
1720 done
1724 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1725 # Meta flavor selection sizes are updated.
1727 build_loram_ram() {
1728 build_initfs ram || return 1
1729 build_loram_rootfs "$1"
1730 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1731 cleanup_efi_boot $TMP_DIR/loramiso
1732 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1733 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1734 update_metaiso_sizes
1735 create_iso $OUTPUT $TMP_DIR/loramiso
1739 # Remove files installed by packages
1741 find_flavor_rootfs() {
1742 for i in $1/etc/tazlito/*.extract; do
1743 [ -e $i ] || continue
1744 chroot $1 /bin/sh ${i#$1}
1745 done
1747 # Clean hardlinks and files patched by genisofs in /boot
1748 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1749 rm -f $1/boot/$i*
1750 done
1752 # Clean files generated in post_install
1753 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1754 $1/dev/core $1/dev/fd $1/dev/std*
1756 # Verify md5
1757 cat $1$INSTALLED/*/md5sum | \
1758 while read md5 file; do
1759 [ -e "$1$file" ] || continue
1760 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1761 rm -f "$1$file"
1762 done
1764 # Check configuration files
1765 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1766 [ -e $i ] || continue
1767 mkdir /tmp/volatile$$
1768 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1769 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1770 while read file ; do
1771 [ -e "$1/$file" ] || continue
1772 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1773 done
1774 rm -rf /tmp/volatile$$
1775 done
1777 # Remove other files blindly
1778 for i in $1$INSTALLED/*/files.list; do
1779 while read file; do
1780 [ "$1$file" -nt "$i" ] && continue
1781 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1782 [ -d "$1$file" ] || rm -f "$1$file"
1783 done < $i
1784 done
1786 # Remove tazpkg files and tmp files
1787 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1788 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1789 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1790 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1791 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1793 # Cleanup directory tree
1794 cd $1
1795 find * -type d | sort -r | while read dir; do
1796 rmdir "$dir" 2>/dev/null
1797 done
1798 cd - > /dev/null
1802 # Get byte(s) from a binary file
1804 get() {
1805 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1809 # Get cpio flavor info from the ISO image
1811 flavordata() {
1812 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1813 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1817 # Restore undigest mirrors
1819 restore_mirrors() {
1820 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1821 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1823 action 'Restoring mirrors...'
1824 if [ -d "$undigest.bak" ]; then
1825 [ -d "$undigest" ] && rm -r "$undigest"
1826 mv "$undigest.bak" "$undigest"
1827 fi
1828 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1829 :; status
1833 # Setup undigest mirrors
1835 setup_mirrors() {
1836 # Setup mirrors in plain system or in chroot (with variable root=)
1837 local mirrorlist="$1" fresh repacked
1838 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1840 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1841 restore_mirrors
1843 _ 'Setting up mirrors for %s...' "$root/"
1844 # Backing up current undigest mirrors and priority
1845 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1846 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1847 rm -rf '/var/www/tazlito/'
1848 mkdir -p '/var/www/tazlito/'
1850 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1851 fresh='/home/slitaz/packages'
1852 if [ -d "$fresh" ]; then
1853 # Setup first undigest mirror
1854 mkdir -p "$undigest/fresh"
1855 echo "$fresh" > "$undigest/fresh/mirror"
1856 echo 'fresh' >> "$priority"
1857 # Rebuild mirror DB if needed
1858 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1859 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1860 tazpkg mkdb "$fresh" --forced --root=''
1861 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1862 fi
1864 # Repacked packages: high priority
1865 repacked="$PACKAGES_REPOSITORY"
1866 if [ -d "$repacked" ] && [ "$repacked" != "$fresh" ] && ls "$repacked" | grep -q '\.tazpkg'; then
1867 # According to Tazlito setup file (tazlito.conf):
1868 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1869 # or
1870 # WORK_DIR="/home/slitaz"
1871 # and
1872 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1873 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1875 # Setup second undigest mirror
1876 mkdir -p "$undigest/repacked"
1877 echo "$repacked" > "$undigest/repacked/mirror"
1878 echo 'repacked' >> "$priority"
1879 # Rebuild mirror DB if needed
1880 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1881 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1882 tazpkg mkdb "$repacked" --forced --root=''
1883 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1884 fi
1886 # All repositories listed in mirrors list: normal priority
1887 [ -e "$mirrorlist" ] && \
1888 while read mirror; do
1889 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1890 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1891 mkdir -p "$undigest/$mirrorid"
1892 echo "$mirror" > "$undigest/$mirrorid/mirror"
1893 echo "$mirrorid" >> "$priority"
1894 done < "$mirrorlist"
1896 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1898 # Show list of mirrors
1899 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1900 function show(num, name, url) {
1901 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1904 num++;
1905 "cat " db "/undigest/" $0 "/mirror" | getline url;
1906 show(num, $0, url);
1908 END {
1909 num++;
1910 "cat " db "/mirror" | getline url;
1911 show(num, "main", url);
1912 }' "$priority"
1914 tazpkg recharge --quiet >/dev/null
1918 # Get list of 'packages.info' lists using priority
1920 pi_lists() {
1921 local pi
1922 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1923 local priority="$root$LOCALSTATE/priority"
1924 local undigest="$root$LOCALSTATE/undigest"
1927 [ -s "$priority" ] && cat "$priority"
1928 echo 'main'
1929 [ -d "$undigest" ] && ls "$undigest"
1930 } | awk -vun="$undigest/" '
1932 if (arr[$0] != 1) {
1933 arr[$0] = 1;
1934 print un $0 "/packages.info";
1936 }' | sed 's|/undigest/main||' | \
1937 while read pi; do
1938 [ -e "$pi" ] && echo "$pi"
1939 done
1943 # Strip versions from packages list
1945 strip_versions() {
1946 if [ -n "$stripped" ]; then
1947 action 'Consider list %s already stripped' "$(basename "$1")"
1948 status
1949 return 0
1950 fi
1951 action 'Strip versions from list %s...' "$(basename "$1")"
1952 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1953 [ -f "$in_list" ] || die "List '$in_list' not found."
1955 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1956 awk '
1958 if (FILENAME ~ "packages.info") {
1959 # Collect package names
1960 FS = "\t"; pkg[$1] = 1;
1961 } else {
1962 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1963 while (NF > 1 && ! pkg[$0])
1964 NF --;
1965 printf "%s\n", $0;
1967 }' $(pi_lists) "$in_list" > "$tmp_list"
1969 cat "$tmp_list" > "$in_list"
1970 rm "$tmp_list"
1971 status
1975 # Display list of unknown packages (informative)
1977 display_unknown() {
1978 [ -s "$1" ] || return
1979 echo "Unknown packages:" >&2
1980 cat "$1" >&2
1981 rm "$1"
1985 # Display warnings about critical packages absent (informative)
1987 display_warn() {
1988 [ -s "$1" ] || return
1989 echo "Absent critical packages:" >&2
1990 cat "$1" >&2
1991 rm "$1"
1992 echo "Probably ISO image will be unusable."
1996 # Install packages to rootfs
1998 install_list_to_rootfs() {
1999 local list="$1" rootfs="$2" pkg i ii
2000 local undigest="$rootfs/var/lib/tazpkg/undigest"
2002 # initial tazpkg setup in empty rootfs
2003 tazpkg --root=$rootfs >/dev/null 2>&1
2004 # pass current 'mirror' to the rootfs
2005 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
2006 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
2007 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
2008 # link rootfs packages cache to the regular packages cache
2009 rm -r "$rootfs/var/cache/tazpkg"
2010 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
2012 setup_mirrors mirrors
2014 # Just in case if flavor doesn't contain "tazlito" package
2015 mkdir -p "$rootfs/etc/tazlito"
2017 newline
2019 # Choose detailed log with --detailed
2020 if [ -n "$detailed" ]; then
2021 while read pkg; do
2022 separator '-'
2023 echo $pkg
2024 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2025 done < $list
2026 separator '='
2027 else
2028 while read pkg; do
2029 action 'Installing package: %s' "$pkg"
2030 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2031 status
2032 done < $list
2033 fi
2034 newline
2036 restore_mirrors
2037 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2038 for i in fresh repacked; do
2039 ii="$undigest/$i"
2040 [ -d "$ii" ] && rm -rf "$ii"
2041 ii="$rootfs/var/lib/tazpkg/priority"
2042 if [ -f "$ii" ]; then
2043 sed -i "/$i/d" "$ii"
2044 [ -s "$ii" ] || rm "$ii"
2045 fi
2046 done
2047 [ -d "$undigest" ] && \
2048 for i in $(find "$undigest" -type f); do
2049 # Remove all undigest PKGDB files but 'mirror'
2050 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2051 done
2052 [ -d "$undigest" ] && \
2053 rmdir --ignore-fail-on-non-empty "$undigest"
2055 # Un-link packages cache
2056 rm "$rootfs/var/cache/tazpkg"
2058 # Clean /var/lib/tazpkg
2059 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2065 ####################
2066 # Tazlito commands #
2067 ####################
2069 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2070 case "$0" in
2071 *reduplicate)
2072 find ${@:-.} ! -type d -links +1 \
2073 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2074 exit 0 ;;
2075 *deduplicate)
2076 deduplicate "$@"
2077 exit 0 ;;
2078 esac
2081 case "$COMMAND" in
2082 stats)
2083 # Tazlito general statistics from the config file.
2085 title 'Tazlito statistics'
2086 optlist "\
2087 Config file : $CONFIG_FILE
2088 ISO name : $ISO_NAME.iso
2089 Volume name : $VOLUM_NAME
2090 Prepared : $PREPARED
2091 Packages repository : $PACKAGES_REPOSITORY
2092 Distro directory : $DISTRO
2093 Additional files : $ADDFILES
2094 " | sed '/: $/d'
2095 footer
2096 ;;
2099 list-addfiles)
2100 # Simple list of additional files in the rootfs
2101 newline
2102 if [ -d "$ADDFILES/rootfs" ]; then
2103 cd $ADDFILES
2104 find rootfs -type f
2105 else
2106 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2107 fi
2108 newline
2109 ;;
2112 gen-config)
2113 # Generate a new config file in the current dir or the specified
2114 # directory by $2.
2116 if [ -n "$2" ]; then
2117 mkdir -p "$2" && cd "$2"
2118 fi
2120 newline
2121 action 'Generating empty tazlito.conf...'
2122 empty_config_file
2123 status
2125 separator
2126 if [ -f 'tazlito.conf' ] ; then
2127 _ 'Configuration file is ready to edit.'
2128 _ 'File location: %s' "$(pwd)/tazlito.conf"
2129 newline
2130 fi
2131 ;;
2134 configure)
2135 # Configure a tazlito.conf config file. Start by getting
2136 # a empty config file and sed it.
2138 if [ -f 'tazlito.conf' ]; then
2139 rm tazlito.conf
2140 else
2141 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2142 'or in the same directory of the file you want to configure.'
2143 cd /etc
2144 fi
2146 empty_config_file
2148 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2150 # ISO name.
2151 echo -n "ISO name : " ; read answer
2152 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2153 # Volume name.
2154 echo -n "Volume name : " ; read answer
2155 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2156 # Packages repository.
2157 echo -n "Packages repository : " ; read answer
2158 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2159 # Distro path.
2160 echo -n "Distro path : " ; read answer
2161 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2162 footer "Config file is ready to use."
2163 echo 'You can now extract an ISO or generate a distro.'
2164 newline
2165 ;;
2168 gen-iso)
2169 # Simply generate a new iso.
2171 check_root
2172 verify_rootcd
2173 gen_livecd_isolinux
2174 distro_stats
2175 ;;
2178 gen-initiso)
2179 # Simply generate a new initramfs with a new iso.
2181 check_root
2182 verify_rootcd
2183 gen_initramfs "$ROOTFS"
2184 gen_livecd_isolinux
2185 distro_stats
2186 ;;
2189 extract-distro|extract-iso)
2190 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2192 check_root
2193 ISO_IMAGE="$2"
2194 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2195 'Example:\n tazlito image.iso /path/target'
2197 # Set the distro path by checking for $3 on cmdline.
2198 TARGET="${3:-$DISTRO}"
2200 # Exit if existing distro is found.
2201 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2202 'Please clean the distro tree or change directory path.'
2204 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2206 # Start to mount the ISO.
2207 action 'Mounting ISO image...'
2208 mkdir -p "$TMP_DIR"
2209 # Get ISO file size.
2210 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2211 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2212 sleep 2
2213 # Prepare target dir, copy the kernel and the rootfs.
2214 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2215 status
2217 action 'Copying the Linux kernel...'
2218 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2219 make_bzImage_hardlink "$TARGET/rootcd/boot"
2220 else
2221 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2222 fi
2223 status
2225 for i in $(ls $TMP_DIR); do
2226 [ "$i" = 'boot' ] && continue
2227 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2228 done
2230 for loader in isolinux syslinux extlinux grub; do
2231 [ -d "$TMP_DIR/boot/$loader" ] || continue
2232 action 'Copying %s files...' "$loader"
2233 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2234 status
2235 done
2237 action 'Copying the rootfs...'
2238 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2239 status
2241 action 'Copying DOS boot files...'
2242 cp $TMP_DIR/boot/linld.com $TMP_DIR/boot/*.exe "$TARGET/rootcd/boot"
2243 status
2245 cleanup_efi_boot "$TARGET/rootcd"
2247 # Extract initramfs.
2248 cd "$TARGET/rootfs"
2249 action 'Extracting the rootfs...'
2250 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2251 extract_rootfs "$i" "$TARGET/rootfs"
2252 done
2253 # unpack /usr
2254 for i in etc/tazlito/*.extract; do
2255 [ -f "$i" ] && . $i ../rootcd
2256 done
2257 # Umount and remove temp directory and cd to $TARGET to get stats.
2258 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2259 cd ..
2260 status
2262 newline
2263 separator
2264 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2265 echo "Distro tree : $(pwd)"
2266 echo "Rootfs size : $(du -sh rootfs)"
2267 echo "Rootcd size : $(du -sh rootcd)"
2268 footer
2269 ;;
2272 list-flavors)
2273 # Show available flavors.
2274 list='/etc/tazlito/flavors.list'
2275 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2276 title 'List of flavors'
2277 cat $list
2278 footer
2279 ;;
2282 show-flavor)
2283 # Show flavor descriptions.
2284 set -e
2285 flavor=${2%.flavor}
2286 flv_dir="$(extract_flavor "$flavor")"
2287 desc="$flv_dir/$flavor.desc"
2288 if [ -n "$brief" ]; then
2289 if [ -z "$noheader" ]; then
2290 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2291 separator
2292 fi
2293 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2294 "$(field ISO "$desc")" \
2295 "$(field Rootfs "$desc")" \
2296 "$(field Description "$desc")"
2297 else
2298 separator
2299 cat "$desc"
2300 fi
2301 cleanup
2302 ;;
2305 gen-liveflavor)
2306 # Generate a new flavor from the live system.
2307 FLAVOR=${2%.flavor}
2308 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2310 case "$FLAVOR" in
2311 -?|-h*|--help)
2312 cat <<EOT
2313 SliTaz Live Tool - Version: $VERSION
2315 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2317 $(boldify '<flavor-patch-file> format:')
2318 $(optlist "\
2319 code data
2320 + package to add
2321 - package to remove
2322 ! non-free package to add
2323 ? display message
2324 @ flavor description
2325 ")
2327 $(boldify 'Example:')
2328 $(optlist "\
2329 @ Developer tools for SliTaz maintainers
2330 + slitaz-toolchain
2331 + mercurial
2332 ")
2333 EOT
2334 exit 1
2335 ;;
2336 esac
2337 mv /etc/tazlito/distro-packages.list \
2338 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2339 rm -f distro-packages.list non-free.list 2>/dev/null
2340 tazpkg recharge
2342 DESC=""
2343 [ -n "$3" ] && \
2344 while read action pkg; do
2345 case "$action" in
2346 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2347 -) yes | tazpkg remove $pkg ;;
2348 !) echo $pkg >> non-free.list ;;
2349 @) DESC="$pkg" ;;
2350 \?) echo -en "$pkg"; read action ;;
2351 esac
2352 done < $3
2354 yes '' | tazlito gen-distro
2355 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2356 mv /etc/tazlito/distro-packages.list.$$ \
2357 /etc/tazlito/distro-packages.list 2>/dev/null
2358 ;;
2361 gen-flavor)
2362 # Generate a new flavor from the last ISO image generated
2363 FLAVOR=${2%.flavor}
2364 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2366 title 'Flavor generation'
2367 check_rootfs
2368 FILES="$FLAVOR.pkglist"
2370 action 'Creating file %s...' "$FLAVOR.flavor"
2371 for i in rootcd rootfs; do
2372 if [ -d "$ADDFILES/$i" ] ; then
2373 FILES="$FILES\n$FLAVOR.$i"
2374 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2375 fi
2376 done
2377 status
2379 answer=$(grep -s ^Description $FLAVOR.desc)
2380 answer=${answer#Description : }
2381 if [ -z "$answer" ]; then
2382 echo -n "Description: "
2383 read answer
2384 fi
2386 action 'Compressing flavor %s...' "$FLAVOR"
2387 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2388 echo "Description : $answer" >> $FLAVOR.desc
2389 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2390 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2391 for i in $(ls $ROOTFS$INSTALLED); do
2392 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2393 EXTRAVERSION=""
2394 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2395 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2396 if [ "$CATEGORY" = 'non-free' ] && [ "${i%%-*}" != 'get' ]; then
2397 echo "$i" >> $FLAVOR.nonfree
2398 else
2399 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2400 fi
2401 done
2402 [ -s $FLAVOR.nonfree ] && FILES="$FILES\n$FLAVOR.nonfree"
2403 for i in $LOCALSTATE/undigest/*/mirror ; do
2404 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2405 done
2406 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2407 touch -t 197001010100.00 $FLAVOR.*
2408 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2409 rm $(echo -e $FILES)
2410 status
2412 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2413 ;;
2416 upgrade-flavor)
2417 # Strip versions from pkglist and update estimated numbers in flavor.desc
2418 flavor="${2%.flavor}"
2419 set -e
2420 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2421 set +e
2423 flv_dir="$(extract_flavor "$flavor")"
2425 strip_versions "$flv_dir/$flavor.pkglist"
2427 action 'Updating %s...' "$flavor.desc"
2429 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2430 set -- $(module calc_sizes "$flv_dir" "$flavor")
2431 restore_mirrors >/dev/null
2433 sed -i -e '/Image is ready/d' \
2434 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2435 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2436 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2437 -e "s|\(Packages *:\).*$|\1 $4|" \
2438 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2439 "$flv_dir/$flavor.desc"
2441 pack_flavor "$flv_dir" "$flavor"
2442 status
2443 display_unknown "$flv_dir/err"
2444 display_warn "$flv_dir/warn"
2445 cleanup
2446 ;;
2449 extract-flavor)
2450 # Extract a flavor into $FLAVORS_REPOSITORY
2451 flavor="${2%.flavor}"
2452 set -e
2453 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2454 set +e
2456 action 'Extracting %s...' "$flavor.flavor"
2457 flv_dir="$(extract_flavor "$flavor" full)"
2458 storage="$FLAVORS_REPOSITORY/$flavor"
2460 rm -rf "$storage" 2>/dev/null
2461 mkdir -p "$storage"
2462 cp -a "$flv_dir"/* "$storage"
2463 rm "$storage/description"
2464 status
2466 strip_versions "$storage/packages.list"
2468 cleanup
2469 ;;
2472 pack-flavor)
2473 # Create a flavor from $FLAVORS_REPOSITORY.
2474 flavor=${2%.flavor}
2475 storage="$FLAVORS_REPOSITORY/$flavor"
2477 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2479 action 'Creating flavor %s...' "$flavor"
2480 tmp_dir="$(mktemp -d)"
2482 while read from to; do
2483 [ -s "$storage/$from" ] || continue
2484 cp -a "$storage/$from" "$tmp_dir/$to"
2485 done <<EOT
2486 mirrors $flavor.mirrors
2487 distro.sh $flavor-distro.sh
2488 receipt $flavor.receipt
2489 non-free.list $flavor.nonfree
2490 EOT
2492 # Build the package list.
2493 # It can include a list from another flavor with the keyword @include
2494 if [ -s "$storage/packages.list" ]; then
2495 include=$(grep '^@include' "$storage/packages.list")
2496 if [ -n "$include" ]; then
2497 include=${include#@include }
2498 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2499 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2500 else
2501 echo -e "\nERROR: Can't find include package list from $include\n"
2502 fi
2503 fi
2504 # Generate the final/initial package list
2505 [ -s "$storage/packages.list" ] && \
2506 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2507 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2508 fi
2510 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2511 # Process multi-rootfs flavor
2512 . "$storage/receipt"
2513 set -- $ROOTFS_SELECTION
2514 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2515 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2516 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2518 for i in rootcd rootfs; do
2519 mkdir "$tmp_dir/$i"
2520 # Copy extra files from the first flavor
2521 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2522 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2523 # Overload extra files by meta flavor
2524 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2525 [ -n "$(ls $tmp_dir/$i)" ] &&
2526 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2527 dogzip "$tmp_dir/$flavor.$i"
2528 rm -rf "$tmp_dir/$i"
2529 done
2530 else
2531 # Process plain flavor
2532 for i in rootcd rootfs; do
2533 [ -d "$storage/$i" ] || continue
2534 (cd "$storage/$i";
2535 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2536 done
2537 fi
2539 unset VERSION MAINTAINER ROOTFS_SELECTION
2540 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2541 ROOTFS_SIZE="$1 (estimated)"
2542 INITRAMFS_SIZE="$2 (estimated)"
2543 ISO_SIZE="$3 (estimated)"
2544 PKGNUM="$4"
2545 . "$storage/receipt"
2547 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2548 Flavor : $FLAVOR
2549 Description : $SHORT_DESC
2550 Version : $VERSION
2551 Maintainer : $MAINTAINER
2552 LiveCD RAM size : $FRUGAL_RAM
2553 Rootfs list : $ROOTFS_SELECTION
2554 Build date : $(date '+%Y%m%d at %T')
2555 Packages : $PKGNUM
2556 Rootfs size : $ROOTFS_SIZE
2557 Initramfs size : $INITRAMFS_SIZE
2558 ISO image size : $ISO_SIZE
2559 ================================================================================
2561 EOT
2563 rm -f $tmp_dir/packages.list
2564 pack_flavor "$tmp_dir" "$flavor"
2565 status
2566 display_unknown "$tmp_dir/err"
2567 display_warn "$flv_dir/warn"
2568 cleanup
2569 ;;
2572 get-flavor)
2573 # Get a flavor's files and prepare for gen-distro.
2574 flavor=${2%.flavor}
2575 title 'Preparing %s distro flavor' "$flavor"
2576 set -e
2577 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2578 set +e
2580 action 'Cleaning %s...' "$DISTRO"
2581 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2582 # Clean old files
2583 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2584 [ -f "$i" ] && rm "$i"
2585 done
2586 mkdir -p "$DISTRO"
2587 status
2589 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2591 action 'Extracting flavor %s...' "$flavor.flavor"
2592 flv_dir="$(extract_flavor "$flavor" info)"
2593 cp -a "$flv_dir"/* .
2594 mv packages.list distro-packages.list
2595 mv -f info /etc/tazlito
2596 status
2598 for i in rootcd rootfs; do
2599 if [ -d "$i" ]; then
2600 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2601 fi
2602 done
2604 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2605 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2607 action 'Updating %s...' 'tazlito.conf'
2608 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2609 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2610 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2611 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2612 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2613 status
2615 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2616 cleanup
2617 ;;
2620 iso2flavor)
2621 [ -z "$3" -o ! -e "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2622 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2624 FLAVOR=${3%.flavor}
2625 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2626 mount -o loop,ro $2 $TMP_DIR/iso
2627 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2628 if [ -s $TMP_DIR/iso/boot/rootfs1.gz ] &&
2629 [ ! -s $TMP_DIR/flavor/*.desc ]; then
2630 _ 'META flavors are not supported.'
2631 umount -d $TMP_DIR/iso
2632 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz ] &&
2633 [ ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2634 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2635 umount -d $TMP_DIR/iso
2636 else
2637 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2638 uncompress $i | \
2639 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2640 done
2641 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2642 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2643 '/etc/slitaz-release' '/boot/rootfs.gz'
2644 umount -d $TMP_DIR/iso
2645 else
2646 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2647 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2648 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2649 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2650 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2651 umount -d $TMP_DIR/iso
2652 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2653 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2654 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2655 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2656 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2657 < $TMP_DIR/rootfs$INSTALLED.md5
2658 PKGCNT=$(grep -cv ^# $TMP_DIR/$FLAVOR.pkglist)
2659 if [ -s $TMP_DIR/flavor/*desc ]; then
2660 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2661 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2662 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2663 for i in rootfs rootcd ; do
2664 [ -s $TMP_DIR/flavor/*.list$i ] &&
2665 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2666 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2667 done
2668 else
2669 find_flavor_rootfs $TMP_DIR/rootfs
2670 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2671 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2672 for i in rootfs rootcd ; do
2673 [ "$(ls $TMP_DIR/$i)" ] &&
2674 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2675 done
2676 unset VERSION MAINTAINER
2677 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2678 if [ -n "$DESCRIPTION" ]; then
2679 _n 'Flavor version : '; read -t 30 VERSION
2680 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2681 fi
2683 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2684 Flavor : $FLAVOR
2685 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2686 Version : ${VERSION:-1.0}
2687 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2688 LiveCD RAM size : $RAM_SIZE
2689 Build date : $BUILD_DATE
2690 Packages : $PKGCNT
2691 Rootfs size : $ROOTFS_SIZE
2692 Initramfs size : $INITRAMFS_SIZE
2693 ISO image size : $ISO_SIZE
2694 ================================================================================
2696 EOT
2697 longline "Tazlito can't detect each file installed during \
2698 a package post_install. You should extract this flavor (tazlito extract-flavor \
2699 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2700 tree and remove files generated by post_installs.
2701 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2702 repack the flavor (tazlito pack-flavor $FLAVOR)"
2703 fi
2704 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2705 fi
2706 fi
2707 rm -rf $TMP_DIR
2708 ;;
2711 gen-distro)
2712 # Generate a live distro tree with a set of packages.
2714 check_root
2715 start_time=$(date +%s)
2717 # Tazlito options: --iso or --cdrom
2718 CDROM=''
2719 [ -n "$iso" ] && CDROM="-o loop $iso"
2720 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2722 # Check if a package list was specified on cmdline.
2723 if [ -f "$2" ]; then
2724 LIST_NAME="$2"
2725 else
2726 LIST_NAME='distro-packages.list'
2727 fi
2729 [ -d "$ROOTFS" ] && [ -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2730 'Please clean the distro tree or change directory path.'
2731 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2732 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2734 # If list not given: build list with all installed packages
2735 if [ ! -f "$LIST_NAME" ] && [ -f "$LOCALSTATE/installed.info" ]; then
2736 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2737 fi
2739 # Exit if no list name.
2740 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2742 # Start generation.
2743 title 'Tazlito generating a distro'
2745 # Misc checks
2746 mkdir -p "$PACKAGES_REPOSITORY"
2747 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2748 newline
2750 # Mount CD-ROM to be able to repack boot-loader packages
2751 if [ ! -e /boot -a -n "$CDROM" ]; then
2752 mkdir $TMP_MNT
2753 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2754 ln -s "$TMP_MNT/boot" /
2755 if [ ! -d "$ADDFILES/rootcd" ] ; then
2756 mkdir -p "$ADDFILES/rootcd"
2757 for i in $(ls $TMP_MNT); do
2758 [ "$i" = 'boot' ] && continue
2759 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2760 done
2761 fi
2762 else
2763 rmdir "$TMP_MNT"
2764 fi
2765 fi
2767 # Rootfs stuff.
2768 echo 'Preparing the rootfs directory...'
2769 mkdir -p "$ROOTFS"
2770 export root="$ROOTFS"
2771 # pass current 'mirror' to the root
2772 mkdir -p $root/var/lib/tazpkg $root/etc
2773 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2774 cp -f /etc/slitaz-release $root/etc/slitaz-release
2775 strip_versions "$LIST_NAME"
2777 if [ "$REPACK" = 'y' ]; then
2778 # Determine full packages list with all dependencies
2779 tmp_dir="$(mktemp -d)"
2780 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2781 touch "$tmp_dir/full.pkglist"
2782 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2784 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2785 while read pkgname pkgver; do
2786 # Is package in full list?
2787 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2788 # Is package already repacked?
2789 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2790 _ 'Repacking %s...' "$pkgname-$pkgver"
2791 tazpkg repack "$pkgname" --quiet
2792 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2793 status
2794 done
2796 rm -r "$tmp_dir"
2797 fi
2799 if [ -f non-free.list ]; then
2800 # FIXME: working in the ROOTFS chroot?
2801 newline
2802 echo 'Preparing non-free packages...'
2803 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2804 while read pkg ; do
2805 if [ ! -d "$INSTALLED/$pkg" ]; then
2806 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2807 tazpkg get-install get-$pkg
2808 fi
2809 get-$pkg "$ROOTFS"
2810 fi
2811 tazpkg repack $pkg
2812 pkg=$(ls $pkg*.tazpkg)
2813 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2814 mv $pkg $PACKAGES_REPOSITORY
2815 done < non-free.list
2816 fi
2817 cp $LIST_NAME $DISTRO/distro-packages.list
2818 newline
2820 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2822 cd $DISTRO
2823 cp distro-packages.list $ROOTFS/etc/tazlito
2824 # Copy all files from $ADDFILES/rootfs to the rootfs.
2825 if [ -d "$ADDFILES/rootfs" ] ; then
2826 action 'Copying addfiles content to the rootfs...'
2827 cp -a $ADDFILES/rootfs/* $ROOTFS
2828 status
2829 fi
2831 action 'Root filesystem is generated...'; status
2833 # Root CD part.
2834 action 'Preparing the rootcd directory...'
2835 mkdir -p $ROOTCD
2836 status
2838 # Move the boot dir with the Linux kernel from rootfs.
2839 # The efi & boot dirs go directly on the CD.
2840 if [ -d "$ROOTFS/efi" ] ; then
2841 action 'Moving the efi directory...'
2842 mv $ROOTFS/efi $ROOTCD
2843 status
2844 fi
2845 if [ -d "$ROOTFS/boot" ] ; then
2846 action 'Moving the boot directory...'
2847 mv $ROOTFS/boot $ROOTCD
2848 status
2849 fi
2850 cd $DISTRO
2851 # Copy all files from $ADDFILES/rootcd to the rootcd.
2852 if [ -d "$ADDFILES/rootcd" ] ; then
2853 action 'Copying addfiles content to the rootcd...'
2854 cp -a $ADDFILES/rootcd/* $ROOTCD
2855 status
2856 fi
2857 # Execute the distro script used to perform tasks in the rootfs
2858 # before compression. Give rootfs path in arg
2859 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2860 if [ -x "$DISTRO_SCRIPT" ]; then
2861 echo 'Executing distro script...'
2862 sh $DISTRO_SCRIPT $DISTRO
2863 fi
2865 # Execute the custom_rules() found in receipt.
2866 if [ -s "$TOP_DIR/receipt" ]; then
2867 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2868 echo -e "Executing: custom_rules()\n"
2869 . "$TOP_DIR/receipt"
2870 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2871 fi
2872 fi
2874 # Multi-rootfs
2875 if [ -s /etc/tazlito/rootfs.list ]; then
2877 FLAVOR_LIST="$(awk '{
2878 for (i = 2; i <= NF; i+=2)
2879 printf "%s ", $i;
2880 }' /etc/tazlito/rootfs.list)"
2882 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2883 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2884 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2886 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2887 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2888 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2889 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2891 n=0
2892 last=$ROOTFS
2893 while read flavor; do
2894 n=$((n+1))
2895 mkdir ${ROOTFS}0$n
2896 export root="${ROOTFS}0$n"
2897 # initial tazpkg setup in empty rootfs
2898 tazpkg --root=$root >/dev/null 2>&1
2900 newline
2901 boldify "Building $flavor rootfs..."
2903 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2904 cp "$TOP_DIR/$flavor.flavor" .
2906 if [ ! -s "$flavor.flavor" ]; then
2907 # We may have it in $FLAVORS_REPOSITORY
2908 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2909 tazlito pack-flavor $flavor
2910 else
2911 download $flavor.flavor
2912 fi
2913 fi
2915 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2916 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2917 cp $flavor.pkglist $DISTRO/list-packages0$n
2918 status
2920 strip_versions "$DISTRO/list-packages0$n"
2922 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2924 action 'Updating the boot directory...'
2925 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2926 rm -rf ${ROOTFS}0$n/boot
2928 cd $DISTRO
2929 if [ -s $flavor.rootfs ]; then
2930 _n 'Adding %s rootfs extra files...' "$flavor"
2931 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2932 fi
2934 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2935 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2936 status
2938 rm -f $flavor.flavor install-list
2939 mergefs ${ROOTFS}0$n $last
2940 last=${ROOTFS}0$n
2941 done <<EOT
2942 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2943 EOT
2944 #'
2945 i=$((n+1))
2946 while [ $n -gt 0 ]; do
2947 mv ${ROOTFS}0$n ${ROOTFS}$i
2948 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2949 gen_initramfs ${ROOTFS}$i
2950 n=$((n-1))
2951 i=$((i-1))
2952 export LZMA_HISTORY_BITS=26
2953 done
2954 mv $ROOTFS ${ROOTFS}$i
2955 gen_initramfs ${ROOTFS}$i
2956 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2957 ROOTFS=${ROOTFS}1
2958 else
2959 # Initramfs and ISO image stuff.
2960 gen_initramfs $ROOTFS
2961 fi
2962 gen_livecd_isolinux
2963 distro_stats
2964 cleanup
2965 ;;
2968 clean-distro)
2969 # Remove old distro tree.
2971 check_root
2972 title 'Cleaning: %s' "$DISTRO"
2973 if [ -d "$DISTRO" ] ; then
2974 if [ -d "$ROOTFS" ] ; then
2975 action 'Removing the rootfs...'
2976 rm -f $DISTRO/$INITRAMFS
2977 rm -rf $ROOTFS
2978 status
2979 fi
2980 if [ -d "$ROOTCD" ] ; then
2981 action 'Removing the rootcd...'
2982 rm -rf $ROOTCD
2983 status
2984 fi
2985 action 'Removing eventual ISO image...'
2986 rm -f $DISTRO/$ISO_NAME.iso
2987 rm -f $DISTRO/$ISO_NAME.md5
2988 status
2989 fi
2990 footer
2991 ;;
2994 check-distro)
2995 # Check for a few LiveCD needed files not installed by packages.
2997 # TODO: Remove this function.
2998 # First two files are maintained by tazpkg while it runs on rootfs,
2999 # while last one file should be maintained by tazlito itself.
3000 check_rootfs
3001 title 'Checking distro: %s' "$ROOTFS"
3002 # SliTaz release info.
3003 rel='/etc/slitaz-release'
3004 if [ ! -f "$ROOTFS$rel" ]; then
3005 _ 'Missing release info: %s' "$rel"
3006 else
3007 action 'Release : %s' "$(cat $ROOTFS$rel)"
3008 status
3009 fi
3010 # Tazpkg mirror.
3011 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
3012 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
3013 todomsg
3014 else
3015 action 'Mirror configuration exists...'
3016 status
3017 fi
3018 # Isolinux msg
3019 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
3020 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
3021 todomsg
3022 else
3023 action 'Isolinux message seems good...'
3024 status
3025 fi
3026 footer
3027 ;;
3030 writeiso)
3031 # Writefs to ISO image including /home unlike gen-distro we don't use
3032 # packages to generate a rootfs, we build a compressed rootfs with all
3033 # the current filesystem similar to 'tazusb writefs'.
3035 DISTRO='/home/slitaz/distro'
3036 ROOTCD="$DISTRO/rootcd"
3037 COMPRESSION="${2:-none}"
3038 ISO_NAME="${3:-slitaz}"
3039 check_root
3040 # Start info
3041 title 'Write filesystem to ISO'
3042 longline "The command writeiso will write the current filesystem into a \
3043 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3044 newline
3045 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3047 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3048 # Save some space
3049 rm -rf /var/cache/tazpkg/*
3050 rm -f /var/lib/tazpkg/*.bak
3051 rm -rf $DISTRO
3053 # Optionally remove sound card selection and screen resolution.
3054 if [ -z $LaunchedByTazpanel ]; then
3055 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3056 case $anser in
3057 y)
3058 action 'Removing current sound card and screen configurations...'
3059 rm -f /var/lib/sound-card-driver
3060 rm -f /var/lib/alsa/asound.state
3061 rm -f /etc/X11/xorg.conf ;;
3062 *)
3063 action 'Keeping current sound card and screen configurations...' ;;
3064 esac
3065 status
3066 newline
3068 # Optionally remove i18n settings
3069 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3070 case $anser in
3071 y)
3072 action 'Removing current locale/keymap settings...'
3073 newline > /etc/locale.conf
3074 newline > /etc/keymap.conf ;;
3075 *)
3076 action 'Keeping current locale/keymap settings...' ;;
3077 esac
3078 status
3079 fi
3081 # Clean-up files by default
3082 newline > /etc/udev/rules.d/70-persistent-net.rules
3083 newline > /etc/udev/rules.d/70-persistant-cd.rules
3085 # Create list of files including default user files since it is defined in /etc/passwd
3086 # and some new users might have been added.
3087 cd /
3088 echo 'init' > /tmp/list
3089 for dir in bin etc sbin var dev lib root usr home opt; do
3090 [ -d $dir ] && find $dir
3091 done >> /tmp/list
3093 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3094 [ -d $dir ] && echo $dir
3095 done >> /tmp/list
3097 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3099 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3100 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3101 #fi
3102 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3103 touch /var/log/wtmp
3105 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3106 sed -i "/var\/log\/$removelog/d" /tmp/list
3107 done
3109 # Generate initramfs with specified compression and display rootfs
3110 # size in realtime.
3111 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3113 write_initramfs &
3114 sleep 2
3115 cd - > /dev/null
3116 echo -en "\nFilesystem size:"
3117 while [ ! -f /tmp/rootfs ]; do
3118 sleep 1
3119 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3120 done
3121 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3122 echo -e "\n"
3123 rm -f /tmp/rootfs
3125 # Move freshly generated rootfs to the cdrom.
3126 mkdir -p $ROOTCD/boot
3127 mv -f /$INITRAMFS $ROOTCD/boot
3128 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3130 # Now we need the kernel and isolinux files.
3131 copy_from_cd() {
3132 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3133 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3134 unmeta_boot $ROOTCD
3135 umount /media/cdrom
3138 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3139 copy_from_cd;
3140 elif mount | grep /media/cdrom; then
3141 copy_from_cd;
3142 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3143 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3144 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3145 else
3146 touch /tmp/.write-iso-error
3147 longline "When SliTaz is running in RAM the kernel and bootloader \
3148 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3149 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3150 echo -en "----\nENTER to continue..."; read i
3151 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3152 copy_from_cd
3153 fi
3155 # Generate the iso image.
3156 touch /tmp/.write-iso
3157 newline
3158 cd $DISTRO
3159 create_iso $ISO_NAME.iso $ROOTCD
3160 action 'Creating the ISO md5sum...'
3161 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3162 status
3164 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3165 rm -f /tmp/.write-iso
3167 if [ -z $LaunchedByTazpanel ]; then
3168 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3169 case $anser in
3170 y)
3171 umount /dev/cdrom 2>/dev/null
3172 eject
3173 echo -n "Please insert a blank CD-ROM and press ENTER..."
3174 read i && sleep 2
3175 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3176 echo -en "----\nENTER to continue..."; read i ;;
3177 *)
3178 exit 0 ;;
3179 esac
3180 fi
3181 ;;
3184 burn-iso)
3185 # Guess CD-ROM device, ask user and burn the ISO.
3187 check_root
3188 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3189 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3190 # We can specify an alternative ISO from the cmdline.
3191 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3192 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3194 title 'Tazlito burn ISO'
3195 echo "CD-ROM device : /dev/$DRIVE_NAME"
3196 echo "Drive speed : $DRIVE_SPEED"
3197 echo "ISO image : $iso"
3198 footer
3200 case $(yesorno 'Burn ISO image?' 'n') in
3201 y)
3202 title 'Starting Wodim to burn the ISO...'
3203 sleep 2
3204 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3205 footer 'ISO image is burned to CD-ROM.'
3206 ;;
3207 *)
3208 die 'Exiting. No ISO burned.'
3209 ;;
3210 esac
3211 ;;
3214 merge)
3215 # Merge multiple rootfs into one iso.
3217 if [ -z "$2" ]; then
3218 cat <<EOT
3219 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3221 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3222 i.e: rootfsN is a subset of rootfsN-1
3223 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3224 The boot loader will select the rootfs according to the RAM size detected.
3226 Example:
3227 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3229 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3230 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3232 EOT
3233 exit 2
3234 fi
3236 shift # skip merge
3237 append="$1 slitaz1"
3238 shift # skip size1
3239 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3241 ISO=$1.merged
3243 # Extract filesystems
3244 action 'Mounting %s' "$1"
3245 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3246 status || cleanup_merge
3248 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3249 make_bzImage_hardlink $TMP_DIR/iso/boot
3250 umount -d $TMP_DIR/mnt
3251 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3252 _ '%s is already a merged iso. Aborting.' "$1"
3253 cleanup_merge
3254 fi
3255 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 ] &&
3256 [ ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3257 if [ ! -f /boot/isolinux/ifmem.c32 ] &&
3258 [ ! -f /boot/isolinux/c32box.c32 ]; then
3259 cat <<EOT
3260 No file /boot/isolinux/ifmem.c32
3261 Please install syslinux package !
3262 EOT
3263 rm -rf $TMP_DIR
3264 exit 1
3265 fi
3266 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3267 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3268 fi
3270 action 'Extracting %s' 'iso/rootfs.gz'
3271 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3272 [ -d $TMP_DIR/rootfs1/etc ]
3273 status || cleanup_merge
3275 n=1
3276 while [ -n "$2" ]; do
3277 shift # skip rootfs N-1
3278 p=$n
3279 n=$((n + 1))
3280 append="$append $1 slitaz$n"
3281 shift # skip size N
3282 mkdir -p $TMP_DIR/rootfs$n
3284 action 'Extracting %s' "$1"
3285 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3286 [ -d "$TMP_DIR/rootfs$n/etc" ]
3287 status || cleanup_merge
3289 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3290 action 'Creating %s' "rootfs$p.gz"
3291 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3292 status
3293 done
3294 action 'Creating %s' "rootfs$n.gz"
3295 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3296 status
3297 rm -f $TMP_DIR/iso/boot/rootfs.gz
3298 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3299 create_iso $ISO $TMP_DIR/iso
3300 rm -rf $TMP_DIR
3301 ;;
3304 repack)
3305 # Repack an iso with maximum lzma compression ratio.
3307 ISO=$2
3308 mkdir -p $TMP_DIR/mnt
3310 # Extract filesystems
3311 action 'Mounting %s' "$ISO"
3312 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3313 status || cleanup_merge
3315 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3316 umount -d $TMP_DIR/mnt
3318 for i in $TMP_DIR/iso/boot/rootfs* ; do
3319 action 'Repacking %s' "$(basename $i)"
3320 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3321 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3322 align_to_32bits $i
3323 status
3324 done
3326 create_iso $ISO $TMP_DIR/iso
3327 rm -rf $TMP_DIR
3328 ;;
3331 build-loram)
3332 # Build a Live CD for low RAM systems.
3334 ISO="$2"
3335 OUTPUT="$3"
3336 [ -z "$3" ] && \
3337 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3338 mkdir -p "$TMP_DIR/iso"
3339 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3340 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3341 if ! check_iso_for_loram ; then
3342 umount -d "$TMP_DIR/iso"
3343 die "$ISO is not a valid SliTaz live CD. Abort."
3344 fi
3345 case "$4" in
3346 cdrom) build_loram_cdrom ;;
3347 http) build_loram_http ;;
3348 *) build_loram_ram "$5" ;;
3349 esac
3350 umount $TMP_DIR/iso # no -d: needs /proc
3351 losetup -d $loopdev
3352 rm -rf $TMP_DIR
3353 ;;
3356 emu-iso)
3357 # Emulate an ISO image with Qemu.
3358 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3359 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3360 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3361 echo -e "\nStarting Qemu emulator:\n"
3362 echo -e "qemu $QEMU_OPTS $iso\n"
3363 qemu $QEMU_OPTS $iso
3364 ;;
3367 deduplicate)
3368 # Deduplicate files in a tree
3369 shift
3370 deduplicate "$@"
3371 ;;
3374 usage|*)
3375 # Print usage also for all unknown commands.
3376 usage
3377 ;;
3378 esac
3380 exit 0