tazlito view tazlito @ rev 530

Add EFI eltorito boot file truncate warning
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Nov 18 09:07:41 2020 +0000 (2020-11-18)
parents 8654e61dc1b3
children 2b9019bb1593
line source
1 #!/bin/sh
2 # TazLito - SliTaz Live Tool.
3 #
4 # Tazlito is a tool to help generate and configure SliTaz Live CD
5 # ISO images. You can create a custom distro in one command from a list of
6 # packages, extract an existing ISO image to hack it, create a new initramfs
7 # and/or a new ISO. Most commands must be run by root, except the stats
8 # and the configuration file manipulation.
9 #
10 # (C) 2007-2018 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
21 alias stat='busybox stat'
22 alias awk='busybox awk'
24 # Tazlito configuration variables to be shorter
25 # and to use words rather than numbers.
26 COMMAND="$1"
27 LIST_NAME="$2"
28 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
29 TMP_MNT="/media/tazlito-$$-$RANDOM"
30 TOP_DIR="$(pwd)"
31 INITRAMFS='rootfs.gz'
32 LOCALSTATE='/var/lib/tazpkg'
33 INSTALLED="$LOCALSTATE/installed"
34 CACHE_DIR='/var/cache/tazpkg'
35 MIRROR="$LOCALSTATE/mirror"
36 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
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 # Download a file from this mirror
178 download_from() {
179 local i mirrors="$1"
180 shift
181 for i in $mirrors; do
182 case "$i" in
183 http://*|ftp://*|https://*)
184 wget -c $i$@ && break;;
185 *)
186 cp $i/$1 . && break;;
187 esac
188 done
189 }
192 # Download a file trying all mirrors
194 download() {
195 local i
196 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
197 download_from "$i" "$@" && break
198 done
199 }
202 # Execute hooks provided by some packages
204 genisohooks() {
205 local here="$(pwd)"
206 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
207 cd $ROOTFS
208 . $i $ROOTCD
209 done
210 cd "$here"
211 }
214 # Echo the package name if the tazpkg is already installed
216 installed_package_name() {
217 local tazpkg="$1" package VERSION EXTRAVERSION
219 # Try to find package name and version to be able
220 # to repack it from installation
221 # A dash (-) can exist in name *and* in version
222 package=${tazpkg%-*}
223 i=$package
224 while true; do
225 unset VERSION EXTRAVERSION
226 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
227 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
228 if [ "$i-$VERSION$EXTRAVERSION" = "$tazpkg" ]; then
229 echo $i
230 break
231 fi
232 case "$i" in
233 *-*);;
234 *) break;;
235 esac
236 i=${i%-*}
237 done
238 }
241 # Check for the rootfs tree.
243 check_rootfs() {
244 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
245 }
248 # Check for the boot dir into the root CD tree.
250 verify_rootcd() {
251 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
252 }
254 set32() {
255 for i in $(seq 0 8 $((${4:-32}-8))); do
256 printf '\\\\x%02X' $((($2 >> $i) & 255))
257 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
258 }
260 set64() {
261 for i in $(seq 0 8 24 ; seq 24 -8 0); do
262 printf '\\\\x%02X' $((($2 >> $i) & 255))
263 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
264 }
267 first_block() {
268 busybox stat -m "$1" | sed q
269 }
273 # Force size and location in the 2nd eltorito boot file (/$efi_img)
275 fix_efi_boot_img_size() {
276 local n=$3
277 # Sector count on 16 bits (max 128MB), see offset 6-7 in page 11 of
278 # https://pdos.csail.mit.edu/6.828/2014/readings/boot-cdrom.pdf
279 [ $n -gt 65535 ] && n=65535 && echo "Warning: truncate EFI eltorito boot file"
280 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
281 set32 $((0x1C+2048*$4)) $(($4*4)) $1
282 }
285 # Force the size for the /$efi_img file
287 fix_efi_img_size() {
288 local e=$((0x809C))
289 for i in $(echo ${efi_img//\// } | tr a-z A-Z) ; do
290 local sz=$(get $(($e+10)) "$2" 4)
291 e=$(($(get $(($e+2)) "$2" 4) * 2048))
292 while [ $sz -gt 0 ]; do
293 local len=$(get $e "$2")
294 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
295 2>/dev/null)" = "$i" ] && continue 2
296 [ $len -eq 0 ] && break
297 sz=$(($sz-$len))
298 e=$(($e+$len))
299 done
300 return # not found
301 done
302 set64 $(($e+10)) $1 "$2"
303 }
306 # create /$efi_img to share EFI files with the iso image
308 fixup_uefi_part() {
309 [ -s $2/$efi_img ] || return
310 [ -x $2/$efi_img ] && return
311 local n=$(get 19 "$2/$efi_img")
312 [ $n -eq 0 ] && n=$(get 32 "$2/$efi_img" 4)
313 efiblock=$(first_block "$2/$efi_img")
314 fix_efi_img_size $(($n*512)) $1
315 fix_efi_boot_img_size $1 $2 $n $efiblock
317 # Build file list tree
318 resv=$(get 14 "$2/$efi_img")
319 if [ $(get 57 "$2/$efi_img" 1) -ne 49 ]; then
320 skiphead=5
321 fatsz=$(get 36 "$2/$efi_img" 4)
322 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
323 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
324 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
325 else
326 skiphead=4
327 fatsz=$(get 22 "$2/$efi_img")
328 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
329 fi 2> /dev/null
330 hd "$2/$efi_img" | awk 'BEGIN { skiphead='$skiphead' }
331 {
332 if (skiphead!=0) {
333 if ($1=="*") skiphead--
334 next
335 }
336 if (skipdot!=0) {
337 if (skipdot==2) up[cur]=$13 $12
338 else cur=$13 $12
339 skipdot=0
340 next
341 }
342 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
343 if ($3=="2e") skipdot=2
344 else skipdot=1
345 next
346 }
347 if (gotname!=0) {
348 path=""
349 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
350 if (gotname==2) dir[$13 $12]=name
351 else print $1 " " $13 $12 " " path name
352 gotname=0
353 name=""
354 next
355 }
356 if (s!="") {
357 if (eos==0)
358 for (i=2;i<18;i+=2) {
359 if (i==12) i+=2
360 if ($i=="00") break
361 s=s substr($0,i+60,1)
362 }
363 name=s name
364 s=""
365 eos=0
366 next
367 }
368 if ($13=="0f") {
369 s=""
370 for (i=3;i<16;i+=2) {
371 if (i==13) i+=3
372 if ($i=="00") { eos=1; break }
373 s=s substr($0,i+60,1)
374 }
375 next
376 }
377 if ($13=="10") {
378 name=name "/"
379 gotname=2
380 next
381 }
382 if ($13=="20") {
383 gotname=1
384 next
385 }
386 }
387 ' | ( while read offset cluster file; do
388 cluster=$(($(first_block "$2/$file")-$basecluster))
389 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
390 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
391 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
392 done
394 # Update fat12 or fat16
395 get 57 "$2/$efi_img"
396 dd if="$2/$efi_img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
397 od -An -t u1 -w1 -v
398 ) | awk '
399 {
400 if (state==0) {
401 if ($2=="") {
402 if ($1==12849) fat=12
403 else if ($1==13873) fat=16
404 else fat=32
405 state++
406 }
407 else {
408 for (i=1;i<$2;i++) c[$1+i]=$1+i
409 c[$1+$2]=268435455
410 }
411 next
412 }
413 if (state==1) {
414 prev=$1
415 state++
416 next
417 }
418 if (state==2) {
419 if (fat==12) {
420 n=($1%16)*256+prev
421 if (n!=0) c[pos+1]=n
422 pos++
423 prev=int($1/16)
424 state++
425 next
426 }
427 n=$1*256+prev
428 if (fat==32) {
429 prev=n
430 state=13
431 next
432 }
433 }
434 else if (state==3) {
435 n=$1*16+prev
436 }
437 else if (state==13) {
438 prev=$1*65536+prev
439 state++
440 next
441 }
442 else n=$1*16777216+prev
443 if (n!=0) c[pos+1]=n
444 pos++
445 state=1
446 }
447 END {
448 for (i=1;i<=pos;i+=2) {
449 if (c[i]=="") c[i]=0
450 if (c[i+1]=="") c[i+1]=0
451 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
452 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
453 else {
454 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
455 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
456 }
457 }
458 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
459 conv=notrunc bs=512 > /dev/null 2>&1
460 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
461 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
463 # Cleanup cache
464 umount $2
465 mount -o loop,ro $1 $2
466 }
469 # allocate efi.img stub to share EFI files in the EFI boot partition
471 alloc_uefi_part() {
472 local basedir=$(dirname "$1")/..
473 if [ -s $basedir/$efi_img ]; then
474 chmod +x $basedir/$efi_img
475 return
476 fi
477 local fclust=$({
478 [ -d $basedir/efi ] &&
479 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
480 while [ -s "$1" ]; do
481 local efifile
482 case "$1" in
483 *taz) efifile=bootia32.efi ;;
484 *taz64) efifile=bootx64.efi ;;
485 esac
486 if [ ! -s $basedir/efi/boot/$efifile ] &&
487 [ $(get $((0x82)) "$1") = $((0x4550)) ]; then
488 mkdir -p $basedir/efi/boot 2> /dev/null
489 ln "$1" "$basedir/efi/boot/$efifile"
490 stat -c "%s %n" "$1"
491 for i in $basedir/boot/rootfs* ; do
492 ln "$i" $basedir/efi/boot/ &&
493 stat -c "%s %n" "$i"
494 done 2> /dev/null
495 [ -s $basedir/efi/boot/linux.cmdline ] ||
496 sed 's|/|\\|g' > $basedir/efi/boot/linux.cmdline <<EOT
497 rw root=0x100$(sed '/bzImage/!d;s|.*root=[^ ]*||;q' $basedir/boot/isolinux/isolinux.cfg)\
498 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
499 echo -n " initrd=/EFI/BOOT/$f";done)
500 EOT
501 fi
502 shift
503 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
504 [ ${fclust:-0} -eq 0 ] && return
505 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
506 BEGIN {
507 FS="/"
508 }
509 NF > 1 {
510 d[NF $NF]+=2
511 d[NF-1 $(NF-1)]+=($NF+25)/13
512 }
513 END {
514 for (i in d)
515 n+=int((d[i]+63)/64)
516 print n
517 }')
518 local clusters=$(($fclust+$dclust))
519 if [ $clusters -lt 4068 ]; then
520 fsect=$(((($clusters+2)*3+1023)/1024))
521 ftype="31 32"
522 fhead="F8 FF FF"
523 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
524 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
525 rootsz=2
526 elif [ $clusters -lt 65525 ]; then
527 fsect=$((($clusters+2+255)/256))
528 ftype="31 36"
529 fhead="F8 FF FF FF"
530 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
531 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
532 rootsz=2
533 else
534 fsect=$((($clusters+2+127)/128))
535 ftype="33 32"
536 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
537 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
538 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
539 rootsz=1
540 fi
541 # reserved + fat*2 + root dir + dirs
542 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
543 s=$((($count+$fclust)*4))
544 if [ $s -gt 65535 ]; then
545 size="00 00"
546 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
547 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
548 else
549 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
550 size32="00 00 00 00"
551 fi
552 dd if=/dev/zero bs=512 of=$basedir/$efi_img \
553 count=$s 2> /dev/null
555 # Create boot sector
556 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
557 if [ "$ftype" = "33 32" ]; then
558 hexdump -R <<EOT | dd of=$basedir/$efi_img \
559 conv=notrunc
560 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
561 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
562 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
563 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
564 0 80 00 29 00 00 00 00 $doslabel |
565 0 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
566 EOT
567 while read ofs data; do
568 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
569 bs=1 seek=$ofs of=$basedir/$efi_img
570 done <<EOT
571 510 55:aa:52:52:61:41
572 996 72:72:41:61:ff:ff:ff:ff:02
573 1022 55:aa
574 EOT
575 else
576 echo -en '\x55\xAA' | dd of=$basedir/$efi_img \
577 seek=510 bs=1 conv=notrunc
578 hexdump -R <<EOT | dd of=$basedir/$efi_img \
579 conv=notrunc
580 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
581 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
582 0 $size32 80 00 29 00 00 00 00 $doslabel |
583 0 46 41 54 $ftype 20 20 20 cd 18 |
584 0 cd 19 eb fa |
585 EOT
586 fi 2> /dev/null
588 # Create fats
589 echo "0 $fhead |" | hexdump -R | dd of=$basedir/$efi_img \
590 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
591 echo "0 $fhead |" | hexdump -R | dd of=$basedir/$efi_img \
592 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
594 # Add label
595 echo "0 $doslabel 08 |" | hexdump -R | \
596 dd of=$basedir/$efi_img bs=512 conv=notrunc \
597 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
599 mkdir -p /tmp/mnt$$
600 mount -o loop $basedir/$efi_img /tmp/mnt$$
601 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
602 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
603 sync
604 dd if=$basedir/$efi_img of=/tmp/fat$$ \
605 skip=$rsect bs=512 count=$fsect 2> /dev/null
606 ( cd $basedir; find efi/boot -type f | cpio -o -H newc ) | \
607 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
608 umount /tmp/mnt$$
609 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/$efi_img \
610 seek=$rsect bs=512 conv=notrunc 2> /dev/null
611 rm /tmp/fat$$
612 rmdir /tmp/mnt$$
614 dd count=0 bs=2k of=$basedir/$efi_img \
615 seek=$count 2> /dev/null
616 }
619 # isolinux.conf doesn't know the kernel version.
620 # We name the kernel image 'bzImage'.
621 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
623 make_bzImage_hardlink() {
624 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
625 rm -f ${1:-.}/bzImage 2>/dev/null
626 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
627 fi
628 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
629 rm -f ${1:-.}/bzImage64 2> /dev/null
630 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
631 fi
632 }
635 create_iso() {
636 cd $2
637 deduplicate
638 sed -i "s|20[1-9][0-9]|$(date +%Y)|" $2/README $2/index.html
640 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
641 make_bzImage_hardlink $2/boot
642 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
644 while read file; do ls -r $file 2> /dev/null; done << EOT | \
645 awk 'BEGIN { n=100 } { print $1 " " n-- }' > /tmp/cdsort$$
646 $PWD/boot/isolinux/boot.cat
647 $PWD/boot/isolinux/isolinux.bin
648 $PWD/boot/isolinux/isolinux.cfg
649 $PWD/boot/isolinux/vesamenu.c32
650 $PWD/boot/isolinux/splash.*g
651 $PWD/boot/isolinux/i18n.cfg
652 $PWD/boot/isolinux/c32box.c32
653 $PWD/boot/isolinux/kbd
654 $PWD/$efi_img
655 $PWD/boot/bzImage*
656 $PWD/efi/boot/linux.cmdline*
657 $PWD/boot/rootfs*
658 EOT
660 action 'Computing md5...'
661 touch $2/boot/isolinux/boot.cat
662 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
663 sort -k 2 > md5sum
664 status
666 cd - >/dev/null
667 title 'Generating ISO image'
669 _ 'Generating %s' "$1"
670 uefi="$(cd $2 ; ls $efi_img 2> /dev/null)"
671 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
672 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
673 -no-emul-boot -boot-load-size 4 -boot-info-table \
674 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
675 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
676 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
677 -A "tazlito $VERSION/$(genisoimage --version)" \
678 -copyright README -P "www.slitaz.org" -no-pad $2
679 rm -f /tmp/cdsort$$
680 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
682 mkdir /tmp/mnt$$
683 mount -o loop,ro $1 /tmp/mnt$$
684 fixup_uefi_part $1 /tmp/mnt$$
685 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
686 ${uefi:+$efi_img} ; do
687 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
688 done
689 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
690 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
691 umount -d /tmp/mnt$$
692 rmdir /tmp/mnt$$
694 if [ -s '/etc/tazlito/info' ]; then
695 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
696 action 'Storing ISO info...'
697 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
698 status
699 fi
700 fi
702 if [ -x '/usr/bin/isohybrid' ]; then
703 action 'Creating hybrid ISO...'
704 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
705 status
706 fi
708 if [ -x '/usr/bin/iso2exe' ]; then
709 echo 'Creating EXE header...'
710 /usr/bin/iso2exe $1 2>/dev/null
711 fi
712 }
715 # Generate a new ISO image using isolinux.
717 gen_livecd_isolinux() {
718 # Some packages may want to alter iso
719 genisohooks iso
720 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
722 # Set date for boot msg.
723 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
724 DATE=$(date +%Y%m%d)
725 action 'Setting build date to: %s...' "$DATE"
726 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
727 status
728 fi
730 cd $DISTRO
731 create_iso $ISO_NAME.iso $ROOTCD
733 action 'Creating the ISO md5sum...'
734 md5sum $ISO_NAME.iso > $ISO_NAME.md5
735 status
737 separator
738 # Some packages may want to alter final iso
739 genisohooks final
740 }
743 lzma_history_bits() {
744 #
745 # This generates an ISO which boots with Qemu but gives
746 # rootfs errors in frugal or liveUSB mode.
747 #
748 # local n
749 # local sz
750 # n=20 # 1Mb
751 # sz=$(du -sk $1 | cut -f1)
752 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
753 # n=$(( $n + 1 ))
754 # sz=$(( $sz / 2 ))
755 # done
756 # echo $n
757 echo ${LZMA_HISTORY_BITS:-24}
758 }
761 lzma_switches() {
762 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
763 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
764 }
767 lzma_set_size() {
768 # Update size field for lzma'd file packed using -si switch
769 return # Need to fix kernel code?
771 local n i
772 n=$(unlzma < $1 | wc -c)
773 for i in $(seq 1 8); do
774 printf '\\\\x%02X' $(($n & 255))
775 n=$(($n >> 8))
776 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
777 }
780 align_to_32bits() {
781 local size=$(stat -c %s ${1:-/dev/null})
782 [ $((${size:-0} & 3)) -ne 0 ] &&
783 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
784 }
787 dolz4() {
788 [ "$(which lz4)" ] || tazpkg get-install lz4
789 lz4 -9 > $1
790 }
793 dogzip() {
794 gzip -9 > $1
795 [ -x /usr/bin/advdef ] && advdef -qz4 $1
796 }
799 # Pack rootfs
801 pack_rootfs() {
802 ( cd $1; find . -print | cpio -o -H newc ) | \
803 case "$COMPRESSION" in
804 none)
805 _ 'Creating %s without compression...' 'initramfs'
806 cat > $2
807 ;;
808 lz4)
809 _ 'Creating %s with lz4 compression...' 'initramfs'
810 dolz4 $2
811 ;;
812 gzip)
813 _ 'Creating %s with gzip compression...' 'initramfs'
814 dogzip $2
815 ;;
816 *)
817 _ 'Creating %s with lzma compression...' 'initramfs'
818 lzma e -si -so $(lzma_switches $1) > $2
819 lzma_set_size $2
820 ;;
821 esac
822 align_to_32bits $2
823 echo 1 > /tmp/rootfs
824 }
827 # Compression functions for writeiso.
829 write_initramfs() {
830 case "$COMPRESSION" in
831 lzma)
832 _n 'Creating %s with lzma compression...' "$INITRAMFS"
833 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
834 align='y'
835 lzma_set_size "/$INITRAMFS"
836 ;;
837 gzip)
838 _ 'Creating %s with gzip compression...' "$INITRAMFS"
839 cpio -o -H newc | dogzip "/$INITRAMFS"
840 ;;
841 lz4)
842 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
843 cpio -o -H newc | dolz4 "/$INITRAMFS"
844 ;;
845 *)
846 # align='y'
847 _ 'Creating %s without compression...' "$INITRAMFS"
848 cpio -o -H newc > "/$INITRAMFS"
849 ;;
850 esac < /tmp/list
851 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
852 echo 1 > /tmp/rootfs
853 }
856 # Deduplicate files (MUST be on the same filesystem).
858 deduplicate() {
859 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
860 (
861 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
862 while read attr inode link file; do
863 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
864 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
865 rm -f "$file"
866 if ln "$old_file" "$file" 2>/dev/null; then
867 hinode="$inode"
868 inode="$old_inode"
869 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
870 save="$(($save+(${attr%%-*}+512)/1024))"
871 continue
872 else
873 cp -p "$old_file" "$file"
874 fi
875 else
876 hinode=""
877 fi
878 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
879 done
880 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
881 )
883 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
884 while read attr inode link file; do
885 echo "$attr-$(readlink "$file" | uuencode -m - | \
886 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
887 done | sort | \
888 (
889 old_attr=""; hardlinks=0;
890 while read attr inode link file; do
891 if [ "$attr" = "$old_attr" ]; then
892 if [ "$inode" != "$old_inode" ]; then
893 rm -f "$file"
894 if ln "$old_file" "$file" 2>/dev/null; then
895 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
896 else
897 cp -a "$old_file" "$file"
898 fi
899 fi
900 else
901 old_file="$file"
902 old_attr="$attr"
903 old_inode="$inode"
904 fi
905 done
906 _ '%s duplicate symlinks.' "$hardlinks"
907 )
908 }
911 # Generate a new initramfs from the root filesystem.
913 gen_initramfs() {
914 # Just in case CTRL+c
915 rm -f $DISTRO/gen
917 # Some packages may want to alter rootfs
918 genisohooks rootfs
919 cd $1
921 # Normalize file time
922 find $1 -newer $1 -exec touch -hr $1 {} \;
924 # Link duplicate files
925 deduplicate
927 # Use lzma if installed. Display rootfs size in realtime.
928 rm -f /tmp/rootfs 2>/dev/null
929 pack_rootfs . $DISTRO/$(basename $1).gz &
930 sleep 2
931 echo -en "\nFilesystem size:"
932 while [ ! -f /tmp/rootfs ]; do
933 sleep 1
934 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
935 done
936 echo -e "\n"
937 rm -f /tmp/rootfs
938 cd $DISTRO
939 mv $(basename $1).gz $ROOTCD/boot
940 }
943 distro_sizes() {
944 if [ -n "$start_time" ]; then
945 time=$(($(date +%s) - $start_time))
946 sec=$time
947 div=$(( ($time + 30) / 60))
948 [ "$div" -ne 0 ] && min="~ ${div}m"
949 _ 'Build time : %ss %s' "$sec" "$min"
950 fi
951 cat <<EOT
952 Build date : $(date +%Y%m%d)
953 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
954 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
955 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
956 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
957 EOT
958 footer "Image is ready: $ISO_NAME.iso"
959 }
962 # Print ISO and rootfs size.
964 distro_stats() {
965 title 'Distro statistics: %s' "$DISTRO"
966 distro_sizes
967 }
970 # Create an empty configuration file.
972 empty_config_file() {
973 cat >> tazlito.conf <<"EOF"
974 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
975 #
977 # Name of the ISO image to generate.
978 ISO_NAME=""
980 # ISO image volume name.
981 VOLUM_NAME="SliTaz"
983 # Name of the preparer.
984 PREPARED="$USER"
986 # Path to the packages repository and the packages.list.
987 PACKAGES_REPOSITORY=""
989 # Path to the distro tree to gen-distro from a list of packages.
990 DISTRO=""
992 # Path to the directory containing additional files
993 # to copy into the rootfs and rootcd of the LiveCD.
994 ADDFILES="$DISTRO/addfiles"
996 # Default answer for binary question (Y or N)
997 DEFAULT_ANSWER="ASK"
999 # Compression utility (lzma, gzip or none)
1000 COMPRESSION="lzma"
1001 EOF
1005 # Extract rootfs.gz somewhere
1007 extract_rootfs() {
1008 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
1009 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1010 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1011 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1012 (cd "$2"; cpio -idm --quiet 2>/dev/null < "$1")
1016 # Extract flavor file to temp directory
1018 extract_flavor() {
1019 # Input: $1 - flavor name to extract;
1020 # $2 = absent/empty: just extract 'outer layer'
1021 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1022 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1023 # Output: temp dir path where flavor was extracted
1024 local f="$1.flavor" from to infos="$1.desc"
1025 [ -f "$f" ] || die "File '$f' not found"
1026 local dir="$(mktemp -d)"
1027 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1029 if [ -n "$2" ]; then
1030 cd $dir
1032 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1034 for i in rootcd rootfs; do
1035 [ -f "$1.$i" ] || continue
1036 mkdir "$i"
1037 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1038 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1039 rm "$1.$i"
1040 done
1041 touch -t 197001010100.00 $1.*
1042 # Info to be stored inside ISO
1043 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1044 rm $1.list*
1046 # Renames
1047 while read from to; do
1048 [ -f "$from" ] || continue
1049 mv "$from" "$to"
1050 done <<EOT
1051 $1.nonfree non-free.list
1052 $1.pkglist packages.list
1053 $1-distro.sh distro.sh
1054 $1.receipt receipt
1055 $1.mirrors mirrors
1056 $1.desc description
1057 EOT
1058 fi
1060 echo $dir
1064 # Pack flavor file from temp directory
1066 pack_flavor() {
1067 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1071 # Remove duplicate files
1073 files_match() {
1074 if [ -d "$1" ]; then
1075 return 1
1077 elif [ -L "$1" ] && [ -L "$2" ]; then
1078 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1080 elif [ -f "$1" ] && [ -f "$2" ]; then
1081 cmp -s "$1" "$2" && return 0
1083 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1084 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1085 return 0
1087 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1088 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1089 return 0
1091 fi 2> /dev/null
1092 return 1
1095 remove_with_path() {
1096 dir="$(dirname $1)"
1097 rm -f "$1"
1098 while rmdir "$dir" 2> /dev/null; do
1099 dir="$(dirname $dir)"
1100 done
1103 mergefs() {
1104 # Note, many packages have files with spaces in the name
1105 IFS=$'\n'
1107 local size1=$(du -hs "$1" | awk '{ print $1 }')
1108 local size2=$(du -hs "$2" | awk '{ print $1 }')
1109 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1111 # merge symlinks files and devices
1112 ( cd "$1"; find ) | \
1113 while read file; do
1114 files_match "$1/$file" "$2/$file" "$file" &&
1115 remove_with_path "$2/$file"
1116 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1117 done
1119 unset IFS
1120 status
1124 cleanup_merge() {
1125 rm -rf $TMP_DIR
1126 exit 1
1130 # Update isolinux config files for multiple rootfs
1132 update_bootconfig() {
1133 local files
1134 action 'Updating boot config files...'
1135 files="$(grep -l 'include common' $1/*.cfg)"
1136 for file in $files; do
1137 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1138 if (/label/) label=$0;
1139 else if (/kernel/) kernel=$0;
1140 else if (/append/) {
1141 i=index($0,"rootfs.gz");
1142 append=substr($0,i+9);
1144 else if (/include/) {
1145 for (i = 1; i <= n; i++) {
1146 print label i
1147 print kernel;
1148 initrd="initrd=/boot/rootfs" n ".gz"
1149 for (j = n - 1; j >= i; j--) {
1150 initrd=initrd ",/boot/rootfs" j ".gz";
1152 printf "\tappend %s%s\n",initrd,append;
1153 print "";
1155 print;
1157 else print;
1158 }' < $file > $file.$$
1159 mv -f $file.$$ $file
1160 done
1161 sel="$(echo $2 | awk '{
1162 for (i=1; i<=NF; i++)
1163 if (i % 2 == 0) printf " slitaz%d", i/2
1164 else printf " %s", $i
1165 }')"
1167 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1169 label slitaz
1170 kernel /boot/isolinux/ifmem.c32
1171 append$sel noram
1173 label noram
1174 config noram.cfg
1176 EOT
1178 # Update vesamenu
1179 if [ -s "$1/isolinux.cfg" ]; then
1180 files="$files $1/isolinux.cfg"
1181 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1182 BEGIN {
1183 kernel = " COM32 c32box.c32"
1186 if (/ROWS/) print "MENU ROWS " n+$3;
1187 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1188 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1189 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1190 else if (/VSHIFT/) {
1191 x = $3-n;
1192 if (x < 0) x = 0;
1193 print "MENU VSHIFT " x;
1195 else if (/rootfs.gz/) {
1196 linux = "";
1197 if (/bzImage/) linux = "linux /boot/bzImage ";
1198 i = index($0, "rootfs.gz");
1199 append = substr($0, i+9);
1200 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1201 printf "\tappend%s noram\n", sel;
1202 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1203 for (i = 1; i <= n; i++) {
1204 print "LABEL slitaz" i
1205 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1206 printf "%s\n", kernel;
1207 initrd = "initrd=/boot/rootfs" n ".gz"
1208 for (j = n - 1; j >= i; j--) {
1209 initrd = initrd ",/boot/rootfs" j ".gz";
1211 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1214 else if (/bzImage/) kernel = $0;
1215 else print;
1216 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1217 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1218 fi
1220 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1221 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1222 cat > $1/noram.cfg <<EOT
1223 implicit 0
1224 prompt 1
1225 timeout 80
1226 $(grep '^F[0-9]' $1/isolinux.cfg)
1228 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1229 say Not enough RAM to boot slitaz. Trying hacker mode...
1230 default hacker
1231 label hacker
1232 KERNEL /boot/bzImage
1233 append rw root=/dev/null vga=normal
1235 label reboot
1236 EOT
1238 if [ -s $1/c32box.c32 ]; then
1239 cat >> $1/noram.cfg <<EOT
1240 COM32 c32box.c32
1241 append reboot
1243 label poweroff
1244 COM32 c32box.c32
1245 append poweroff
1247 EOT
1248 else
1249 echo " com32 reboot.c32" >> $1/noram.cfg
1250 fi
1252 # Restore real label names
1253 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1254 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1255 while read pat; do
1256 sed -i "s/slitaz$pat/" $files
1257 done
1258 status
1262 # Uncompress rootfs or module to stdout
1264 uncompress() {
1265 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1266 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1270 # Install a missing package
1272 install_package() {
1273 if [ -z "$2" ]; then
1274 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1275 else
1276 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1277 fi
1278 case "$answer" in
1279 y)
1280 # We don't want package on host cache.
1281 action 'Getting and installing package: %s' "$1"
1282 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1283 status ;;
1284 *)
1285 return 1 ;;
1286 esac
1290 # Check iso for loram transformation
1292 check_iso_for_loram() {
1293 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1294 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1298 # Remove duplicated files in $1/efi/boot from $1/boot
1300 cleanup_efi_boot() {
1301 for i in $1/$efi_img $1/boot/isolinux/efi.img ; do
1302 [ -s $i ] && [ ! -x $i ] && rm -f $i
1303 done
1304 for i in $1/efi/boot/* ; do
1305 [ -f $i ] || continue
1306 case "$i" in
1307 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1308 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1309 rm $1/efi/boot/linux.cmdline ;;
1310 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1311 rm $1/efi/boot/linux.cmdline* ;;
1312 esac
1313 rm -f $i
1314 rmdir $1/efi/boot && rmdir $1/efi
1315 done 2> /dev/null
1319 # Build initial rootfs for loram ISO ram/cdrom/http
1321 build_initfs() {
1322 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1323 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1324 mirror3.slitaz.org mirror.slitaz.org"
1325 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1326 [ -z "$version" ] && die "Can't find the kernel version." \
1327 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1329 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1330 need_lib=false
1331 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1332 mkdir -p $TMP_DIR/initfs/$i
1333 done
1334 ln -s bin $TMP_DIR/initfs/sbin
1335 ln -s . $TMP_DIR/initfs/usr
1336 for aufs in aufs overlayfs; do
1337 for v in $version ; do
1338 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1339 install_package ${v/*taz/linux}-$aufs $v && continue
1340 done
1341 install_package $aufs $version && break
1342 done || return 1
1343 [ -s /init ] || install_package slitaz-boot-scripts
1344 cp /init $TMP_DIR/initfs/
1345 for v in $version ; do
1346 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1347 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1348 done
1349 if [ "$1" = 'cdrom' ]; then
1350 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1351 else
1352 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1353 for v in $version ; do
1354 while [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; do
1355 install_package linux-squashfs $v || return 1
1356 done
1357 done
1358 for v in $version ; do
1359 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1360 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1361 done
1362 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1363 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1364 fi
1365 if [ "$1" = 'http' ]; then
1366 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1367 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1368 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1369 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1370 cp -a /dev/fuse $TMP_DIR/initfs/dev
1371 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1372 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1373 else
1374 need_lib=true
1375 fi
1376 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1377 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1378 else
1379 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1380 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1381 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1382 cp -a /lib/librt* $TMP_DIR/initfs/lib
1383 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1384 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1385 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1386 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1387 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1388 need_lib=true
1389 fi
1390 cd $TMP_DIR/fs
1391 echo 'Getting slitaz-release & ethernet modules...'
1392 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1393 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1394 [ -s rootfs* ] || continue
1395 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1396 rm -f rootfs*
1397 done 2>&1 > /dev/null
1398 cd - > /dev/null
1399 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1400 for v in $version ; do
1401 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1402 -type f -name '*.ko*' | while read mod; do
1403 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1404 uncompress $mod > $f
1405 grep -q alias=pci: $f || rm -f $f
1406 done
1407 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1408 f=$(basename $i)..z
1409 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1410 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1411 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1412 for j in $deps; do
1413 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1414 uncompress $mod > $(echo $j | sed s/..z$//)
1415 done
1416 done
1417 done
1418 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"
1419 _n 'List of URLs to insert: '
1420 read -t 30 urliso2
1421 urliso="$urliso2 $urliso"
1422 fi
1423 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1424 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1425 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1426 else
1427 cp /bin/busybox $TMP_DIR/initfs/bin
1428 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1429 cp /sbin/insmod $TMP_DIR/initfs/bin
1430 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1431 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1432 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1433 fi
1434 need_lib=true
1435 fi
1436 bins="sh switch_root"
1437 [ "$(echo ls | chroot $TMP_DIR/initfs busybox sh 2> /dev/null)" ] ||
1438 bins="$($TMP_DIR/initfs/bin/busybox | awk \
1439 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g')"
1440 for i in $bins ; do
1441 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1442 done
1443 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1444 for v in $version ; do
1445 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1446 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1447 done
1448 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1449 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1450 cp -a $i $TMP_DIR/initfs/dev
1451 done
1452 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1453 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1454 cp -a $i $TMP_DIR/initfs/dev
1455 done 2>/dev/null
1456 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1457 cp -a $i $TMP_DIR/initfs/lib
1458 done
1459 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1460 #!/bin/sh
1462 getarg() {
1463 grep -q " \$1=" /proc/cmdline || return 1
1464 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1465 return 0
1468 copy_rootfs() {
1469 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1470 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1471 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1472 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1473 path=/mnt/
1474 return 0
1475 else
1476 rm -f /mnt/rootfs*
1477 return 1
1478 fi
1481 echo "Switching / to tmpfs..."
1482 mount -t proc proc /proc
1483 size="\$(grep rootfssize= < /proc/cmdline | \\
1484 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1485 [ -n "\$size" ] || size="-o size=90%"
1487 mount -t sysfs sysfs /sys
1488 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1489 [ -s \$i ] && continue
1490 echo -en "Probe \$i \\r"
1491 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1492 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1493 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1494 insmod /lib/modules/\$k.ko 2> /dev/null
1495 done
1496 echo "Loading \$i"
1497 insmod \$i 2> /dev/null
1498 break
1499 done
1500 done
1501 umount /sys
1502 while read var default; do
1503 eval \$var=\$default
1504 getarg \$var \$var
1505 done <<EOT
1506 eth eth0
1507 dns 208.67.222.222,208.67.220.220
1508 netmask 255.255.255.0
1509 gw
1510 ip
1511 EOT
1512 grep -q \$eth /proc/net/dev || sh
1513 if [ -n "\$ip" ]; then
1514 ifconfig \$eth \$ip netmask \$netmask up
1515 route add default gateway \$gw
1516 for i in \$(echo \$dns | sed 's/,/ /g'); do
1517 echo "nameserver \$i" >> /etc/resolv.conf
1518 done
1519 else
1520 udhcpc -f -q -s /lib/udhcpc -i \$eth
1521 fi
1522 for i in $urliso ; do
1523 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1524 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"
1525 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1526 done
1527 getarg urliso URLISO
1528 DIR=fs
1529 if getarg loram DIR; then
1530 DEVICE=\${DIR%,*}
1531 DIR=/\${DIR#*,}
1532 fi
1533 mount -t tmpfs \$size tmpfs /mnt
1534 path2=/mnt/.httpfs/
1535 path=/mnt/.cdrom/
1536 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1537 while [ ! -d \$path/boot ]; do
1538 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1539 httpfs \$i \$path2 && echo \$i && break
1540 done
1541 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1542 done
1544 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1545 umount /proc
1546 branch=:/mnt/.cdrom/\$DIR
1547 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1548 branch=
1549 lp=1
1550 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1551 [ -s \$i ] && insmod \$i
1552 done 2> /dev/null
1553 for i in \${path}boot/rootfs?.* ; do
1554 fs=\${i#*root}
1555 branch=\$branch:/mnt/.\$fs
1556 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1557 losetup -o 124 /dev/loop\$lp \$i
1558 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1559 lp=\$((\$lp+1))
1560 done
1561 fi
1562 mkdir -p /mnt/.rw/mnt/.httpfs
1563 while read type opt; do
1564 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1565 [ -s \$i ] && insmod \$i &&
1566 mount -t \$type -o \$opt none /mnt && break 2
1567 done
1568 done <<EOT
1569 aufs br=/mnt/.rw\$branch
1570 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1571 EOT
1572 rm -rf /lib/modules
1573 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1574 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1575 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1576 EOTEOT
1577 chmod +x $TMP_DIR/initfs/init
1578 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1579 [ -s $i ] || continue
1580 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1581 rm -f $i
1582 done 2>/dev/null
1583 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1584 lzma e $TMP_DIR/initfs.gz -si
1585 lzma_set_size $TMP_DIR/initfs.gz
1586 rm -rf $TMP_DIR/initfs
1587 align_to_32bits $TMP_DIR/initfs.gz
1588 return 0
1592 # Move each initramfs to squashfs
1594 build_loram_rootfs() {
1595 rootfs_sizes=""
1596 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1597 mkdir -p $TMP_DIR/fs
1598 cd $TMP_DIR/fs
1599 uncompress $i | cpio -idm
1600 deduplicate
1601 cd - > /dev/null
1602 rootfs=$TMP_DIR/$(basename $i 64)
1603 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1604 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1605 cd $TMP_DIR
1606 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1607 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1608 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1609 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1610 rm -f $rootfs
1611 mv ${rootfs%64}.cpio $rootfs
1612 cd - > /dev/null
1613 rm -rf $TMP_DIR/fs
1614 done
1618 # Move meta boot configuration files to basic configuration files
1619 # because meta loram flavor is useless when rootfs is not loaded in RAM
1621 unmeta_boot() {
1622 local root=${1:-$TMP_DIR/loramiso}
1623 if [ -f $root/boot/isolinux/noram.cfg ]; then
1624 # We keep enough information to do unloram...
1625 [ -s $root/boot/isolinux/common.cfg ] &&
1626 sed -i 's/label slitaz/label orgslitaz/' \
1627 $root/boot/isolinux/common.cfg
1628 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1629 shift
1630 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1631 $root/boot/isolinux/isolinux.cfg
1632 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1633 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1634 $root/boot/isolinux/*.cfg
1635 fi
1639 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1640 # These squashfs may be loaded in RAM at boot time.
1641 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1642 # Meta flavors are converted to normal flavors.
1644 build_loram_cdrom() {
1645 build_initfs cdrom || return 1
1646 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1647 cleanup_efi_boot $TMP_DIR/loramiso
1648 mkdir $TMP_DIR/loramiso/fs
1649 cd $TMP_DIR/loramiso/fs
1650 for i in $( ls ../boot/root* | sort -r ) ; do
1651 uncompress $i | cpio -idmu
1652 rm -f $i
1653 done
1654 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1655 cd - >/dev/null
1656 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1657 unmeta_boot
1658 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1659 busybox sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1660 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1661 busybox sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' \
1662 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1663 create_iso $OUTPUT $TMP_DIR/loramiso
1667 # Create http bootstrap to load and remove loram_cdrom
1668 # Meta flavors are converted to normal flavors.
1670 build_loram_http() {
1671 build_initfs http || return 1
1672 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1673 cleanup_efi_boot $TMP_DIR/loramiso
1674 rm -f $TMP_DIR/loramiso/boot/rootfs*
1675 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1676 unmeta_boot
1677 create_iso $OUTPUT $TMP_DIR/loramiso
1681 # Update meta flavor selection sizes.
1682 # Reduce sizes with rootfs gains.
1684 update_metaiso_sizes() {
1685 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1686 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1687 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1688 do
1689 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1690 local sizes="$rootfs_sizes"
1691 local new
1692 set -- $append
1693 shift
1694 [ "$1" = "ifmem" ] && shift
1695 new=""
1696 while [ -n "$2" ]; do
1697 local s
1698 case "$1" in
1699 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1700 *M) s=$(( ${1%M} * 1024 ));;
1701 *) s=${1%K};;
1702 esac
1703 sizes=${sizes#* }
1704 for i in $sizes ; do
1705 s=$(( $s - $i ))
1706 done
1707 new="$new $s $2"
1708 shift 2
1709 done
1710 busybox sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1711 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1712 busybox sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1713 busybox sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1714 busybox sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' $cfg
1715 done
1719 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1720 # Meta flavor selection sizes are updated.
1722 build_loram_ram() {
1723 build_initfs ram || return 1
1724 build_loram_rootfs "$1"
1725 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1726 cleanup_efi_boot $TMP_DIR/loramiso
1727 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1728 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1729 update_metaiso_sizes
1730 create_iso $OUTPUT $TMP_DIR/loramiso
1734 # Remove files installed by packages
1736 find_flavor_rootfs() {
1737 for i in $1/etc/tazlito/*.extract; do
1738 [ -e $i ] || continue
1739 chroot $1 /bin/sh ${i#$1}
1740 done
1742 # Clean hardlinks and files patched by genisofs in /boot
1743 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1744 rm -f $1/boot/$i*
1745 done
1747 # Clean files generated in post_install
1748 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1749 $1/dev/core $1/dev/fd $1/dev/std*
1751 # Verify md5
1752 cat $1$INSTALLED/*/md5sum | \
1753 while read md5 file; do
1754 [ -e "$1$file" ] || continue
1755 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1756 rm -f "$1$file"
1757 done
1759 # Check configuration files
1760 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1761 [ -e $i ] || continue
1762 mkdir /tmp/volatile$$
1763 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1764 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1765 while read file ; do
1766 [ -e "$1/$file" ] || continue
1767 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1768 done
1769 rm -rf /tmp/volatile$$
1770 done
1772 # Remove other files blindly
1773 for i in $1$INSTALLED/*/files.list; do
1774 while read file; do
1775 [ "$1$file" -nt "$i" ] && continue
1776 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1777 [ -d "$1$file" ] || rm -f "$1$file"
1778 done < $i
1779 done
1781 # Remove tazpkg files and tmp files
1782 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1783 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1784 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1785 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1786 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1788 # Cleanup directory tree
1789 cd $1
1790 find * -type d | sort -r | while read dir; do
1791 rmdir "$dir" 2>/dev/null
1792 done
1793 cd - > /dev/null
1797 # Get byte(s) from a binary file
1799 get() {
1800 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1804 # Get cpio flavor info from the ISO image
1806 flavordata() {
1807 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1808 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1812 # Restore undigest mirrors
1814 restore_mirrors() {
1815 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1816 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1818 action 'Restoring mirrors...'
1819 if [ -d "$undigest.bak" ]; then
1820 [ -d "$undigest" ] && rm -r "$undigest"
1821 mv "$undigest.bak" "$undigest"
1822 fi
1823 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1824 :; status
1828 # Setup undigest mirrors
1830 setup_mirrors() {
1831 # Setup mirrors in plain system or in chroot (with variable root=)
1832 local mirrorlist="$1" fresh repacked
1833 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1835 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1836 restore_mirrors
1838 _ 'Setting up mirrors for %s...' "$root/"
1839 # Backing up current undigest mirrors and priority
1840 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1841 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1842 rm -rf '/var/www/tazlito/'
1843 mkdir -p '/var/www/tazlito/'
1845 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1846 fresh='/home/slitaz/packages'
1847 if [ -d "$fresh" ]; then
1848 # Setup first undigest mirror
1849 mkdir -p "$undigest/fresh"
1850 echo "$fresh" > "$undigest/fresh/mirror"
1851 echo 'fresh' >> "$priority"
1852 # Rebuild mirror DB if needed
1853 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1854 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1855 tazpkg mkdb "$fresh" --forced --root=''
1856 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1857 fi
1859 # Repacked packages: high priority
1860 repacked="$PACKAGES_REPOSITORY"
1861 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1862 # According to Tazlito setup file (tazlito.conf):
1863 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1864 # or
1865 # WORK_DIR="/home/slitaz"
1866 # and
1867 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1868 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1870 # Setup second undigest mirror
1871 mkdir -p "$undigest/repacked"
1872 echo "$repacked" > "$undigest/repacked/mirror"
1873 echo 'repacked' >> "$priority"
1874 # Rebuild mirror DB if needed
1875 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1876 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1877 tazpkg mkdb "$repacked" --forced --root=''
1878 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1879 fi
1881 # All repositories listed in mirrors list: normal priority
1882 [ -e "$mirrorlist" ] && \
1883 while read mirror; do
1884 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1885 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1886 mkdir -p "$undigest/$mirrorid"
1887 echo "$mirror" > "$undigest/$mirrorid/mirror"
1888 echo "$mirrorid" >> "$priority"
1889 done < "$mirrorlist"
1891 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1893 # Show list of mirrors
1894 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1895 function show(num, name, url) {
1896 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1899 num++;
1900 "cat " db "/undigest/" $0 "/mirror" | getline url;
1901 show(num, $0, url);
1903 END {
1904 num++;
1905 "cat " db "/mirror" | getline url;
1906 show(num, "main", url);
1907 }' "$priority"
1909 tazpkg recharge --quiet >/dev/null
1913 # Get list of 'packages.info' lists using priority
1915 pi_lists() {
1916 local pi
1917 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1918 local priority="$root$LOCALSTATE/priority"
1919 local undigest="$root$LOCALSTATE/undigest"
1922 [ -s "$priority" ] && cat "$priority"
1923 echo 'main'
1924 [ -d "$undigest" ] && ls "$undigest"
1925 } | awk -vun="$undigest/" '
1927 if (arr[$0] != 1) {
1928 arr[$0] = 1;
1929 print un $0 "/packages.info";
1931 }' | sed 's|/undigest/main||' | \
1932 while read pi; do
1933 [ -e "$pi" ] && echo "$pi"
1934 done
1938 # Strip versions from packages list
1940 strip_versions() {
1941 if [ -n "$stripped" ]; then
1942 action 'Consider list %s already stripped' "$(basename "$1")"
1943 status
1944 return 0
1945 fi
1946 action 'Strip versions from list %s...' "$(basename "$1")"
1947 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1948 [ -f "$in_list" ] || die "List '$in_list' not found."
1950 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1951 awk '
1953 if (FILENAME ~ "packages.info") {
1954 # Collect package names
1955 FS = "\t"; pkg[$1] = 1;
1956 } else {
1957 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1958 while (NF > 1 && ! pkg[$0])
1959 NF --;
1960 printf "%s\n", $0;
1962 }' $(pi_lists) "$in_list" > "$tmp_list"
1964 cat "$tmp_list" > "$in_list"
1965 rm "$tmp_list"
1966 status
1970 # Display list of unknown packages (informative)
1972 display_unknown() {
1973 [ -s "$1" ] || return
1974 echo "Unknown packages:" >&2
1975 cat "$1" >&2
1976 rm "$1"
1980 # Display warnings about critical packages absent (informative)
1982 display_warn() {
1983 [ -s "$1" ] || return
1984 echo "Absent critical packages:" >&2
1985 cat "$1" >&2
1986 rm "$1"
1987 echo "Probably ISO image will be unusable."
1991 # Install packages to rootfs
1993 install_list_to_rootfs() {
1994 local list="$1" rootfs="$2" pkg i ii
1995 local undigest="$rootfs/var/lib/tazpkg/undigest"
1997 # initial tazpkg setup in empty rootfs
1998 tazpkg --root=$rootfs >/dev/null 2>&1
1999 # pass current 'mirror' to the rootfs
2000 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
2001 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
2002 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
2003 # link rootfs packages cache to the regular packages cache
2004 rm -r "$rootfs/var/cache/tazpkg"
2005 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
2007 setup_mirrors mirrors
2009 # Just in case if flavor doesn't contain "tazlito" package
2010 mkdir -p "$rootfs/etc/tazlito"
2012 newline
2014 # Choose detailed log with --detailed
2015 if [ -n "$detailed" ]; then
2016 while read pkg; do
2017 separator '-'
2018 echo $pkg
2019 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2020 done < $list
2021 separator '='
2022 else
2023 while read pkg; do
2024 action 'Installing package: %s' "$pkg"
2025 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2026 status
2027 done < $list
2028 fi
2029 newline
2031 restore_mirrors
2032 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2033 for i in fresh repacked; do
2034 ii="$undigest/$i"
2035 [ -d "$ii" ] && rm -rf "$ii"
2036 ii="$rootfs/var/lib/tazpkg/priority"
2037 if [ -f "$ii" ]; then
2038 sed -i "/$i/d" "$ii"
2039 [ -s "$ii" ] || rm "$ii"
2040 fi
2041 done
2042 [ -d "$undigest" ] && \
2043 for i in $(find "$undigest" -type f); do
2044 # Remove all undigest PKGDB files but 'mirror'
2045 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2046 done
2047 [ -d "$undigest" ] && \
2048 rmdir --ignore-fail-on-non-empty "$undigest"
2050 # Un-link packages cache
2051 rm "$rootfs/var/cache/tazpkg"
2053 # Clean /var/lib/tazpkg
2054 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2060 ####################
2061 # Tazlito commands #
2062 ####################
2064 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2065 case "$0" in
2066 *reduplicate)
2067 find ${@:-.} ! -type d -links +1 \
2068 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2069 exit 0 ;;
2070 *deduplicate)
2071 deduplicate "$@"
2072 exit 0 ;;
2073 esac
2076 case "$COMMAND" in
2077 stats)
2078 # Tazlito general statistics from the config file.
2080 title 'Tazlito statistics'
2081 optlist "\
2082 Config file : $CONFIG_FILE
2083 ISO name : $ISO_NAME.iso
2084 Volume name : $VOLUM_NAME
2085 Prepared : $PREPARED
2086 Packages repository : $PACKAGES_REPOSITORY
2087 Distro directory : $DISTRO
2088 Additional files : $ADDFILES
2089 " | sed '/: $/d'
2090 footer
2091 ;;
2094 list-addfiles)
2095 # Simple list of additional files in the rootfs
2096 newline
2097 if [ -d "$ADDFILES/rootfs" ]; then
2098 cd $ADDFILES
2099 find rootfs -type f
2100 else
2101 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2102 fi
2103 newline
2104 ;;
2107 gen-config)
2108 # Generate a new config file in the current dir or the specified
2109 # directory by $2.
2111 if [ -n "$2" ]; then
2112 mkdir -p "$2" && cd "$2"
2113 fi
2115 newline
2116 action 'Generating empty tazlito.conf...'
2117 empty_config_file
2118 status
2120 separator
2121 if [ -f 'tazlito.conf' ] ; then
2122 _ 'Configuration file is ready to edit.'
2123 _ 'File location: %s' "$(pwd)/tazlito.conf"
2124 newline
2125 fi
2126 ;;
2129 configure)
2130 # Configure a tazlito.conf config file. Start by getting
2131 # a empty config file and sed it.
2133 if [ -f 'tazlito.conf' ]; then
2134 rm tazlito.conf
2135 else
2136 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2137 'or in the same directory of the file you want to configure.'
2138 cd /etc
2139 fi
2141 empty_config_file
2143 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2145 # ISO name.
2146 echo -n "ISO name : " ; read answer
2147 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2148 # Volume name.
2149 echo -n "Volume name : " ; read answer
2150 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2151 # Packages repository.
2152 echo -n "Packages repository : " ; read answer
2153 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2154 # Distro path.
2155 echo -n "Distro path : " ; read answer
2156 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2157 footer "Config file is ready to use."
2158 echo 'You can now extract an ISO or generate a distro.'
2159 newline
2160 ;;
2163 gen-iso)
2164 # Simply generate a new iso.
2166 check_root
2167 verify_rootcd
2168 gen_livecd_isolinux
2169 distro_stats
2170 ;;
2173 gen-initiso)
2174 # Simply generate a new initramfs with a new iso.
2176 check_root
2177 verify_rootcd
2178 gen_initramfs "$ROOTFS"
2179 gen_livecd_isolinux
2180 distro_stats
2181 ;;
2184 extract-distro|extract-iso)
2185 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2187 check_root
2188 ISO_IMAGE="$2"
2189 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2190 'Example:\n tazlito image.iso /path/target'
2192 # Set the distro path by checking for $3 on cmdline.
2193 TARGET="${3:-$DISTRO}"
2195 # Exit if existing distro is found.
2196 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2197 'Please clean the distro tree or change directory path.'
2199 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2201 # Start to mount the ISO.
2202 action 'Mounting ISO image...'
2203 mkdir -p "$TMP_DIR"
2204 # Get ISO file size.
2205 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2206 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2207 sleep 2
2208 # Prepare target dir, copy the kernel and the rootfs.
2209 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2210 status
2212 action 'Copying the Linux kernel...'
2213 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2214 make_bzImage_hardlink "$TARGET/rootcd/boot"
2215 else
2216 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2217 fi
2218 status
2220 for i in $(ls $TMP_DIR); do
2221 [ "$i" = 'boot' ] && continue
2222 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2223 done
2225 for loader in isolinux syslinux extlinux grub; do
2226 [ -d "$TMP_DIR/boot/$loader" ] || continue
2227 action 'Copying %s files...' "$loader"
2228 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2229 status
2230 done
2232 action 'Copying the rootfs...'
2233 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2234 status
2236 cleanup_efi_boot "$TARGET/rootcd"
2238 # Extract initramfs.
2239 cd "$TARGET/rootfs"
2240 action 'Extracting the rootfs...'
2241 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2242 extract_rootfs "$i" "$TARGET/rootfs"
2243 done
2244 # unpack /usr
2245 for i in etc/tazlito/*.extract; do
2246 [ -f "$i" ] && . $i ../rootcd
2247 done
2248 # Umount and remove temp directory and cd to $TARGET to get stats.
2249 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2250 cd ..
2251 status
2253 newline
2254 separator
2255 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2256 echo "Distro tree : $(pwd)"
2257 echo "Rootfs size : $(du -sh rootfs)"
2258 echo "Rootcd size : $(du -sh rootcd)"
2259 footer
2260 ;;
2263 list-flavors)
2264 # Show available flavors.
2265 list='/etc/tazlito/flavors.list'
2266 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2267 title 'List of flavors'
2268 cat $list
2269 footer
2270 ;;
2273 show-flavor)
2274 # Show flavor descriptions.
2275 set -e
2276 flavor=${2%.flavor}
2277 flv_dir="$(extract_flavor "$flavor")"
2278 desc="$flv_dir/$flavor.desc"
2279 if [ -n "$brief" ]; then
2280 if [ -z "$noheader" ]; then
2281 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2282 separator
2283 fi
2284 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2285 "$(field ISO "$desc")" \
2286 "$(field Rootfs "$desc")" \
2287 "$(field Description "$desc")"
2288 else
2289 separator
2290 cat "$desc"
2291 fi
2292 cleanup
2293 ;;
2296 gen-liveflavor)
2297 # Generate a new flavor from the live system.
2298 FLAVOR=${2%.flavor}
2299 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2301 case "$FLAVOR" in
2302 -?|-h*|--help)
2303 cat <<EOT
2304 SliTaz Live Tool - Version: $VERSION
2306 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2308 $(boldify '<flavor-patch-file> format:')
2309 $(optlist "\
2310 code data
2311 + package to add
2312 - package to remove
2313 ! non-free package to add
2314 ? display message
2315 @ flavor description
2316 ")
2318 $(boldify 'Example:')
2319 $(optlist "\
2320 @ Developer tools for SliTaz maintainers
2321 + slitaz-toolchain
2322 + mercurial
2323 ")
2324 EOT
2325 exit 1
2326 ;;
2327 esac
2328 mv /etc/tazlito/distro-packages.list \
2329 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2330 rm -f distro-packages.list non-free.list 2>/dev/null
2331 tazpkg recharge
2333 DESC=""
2334 [ -n "$3" ] && \
2335 while read action pkg; do
2336 case "$action" in
2337 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2338 -) yes | tazpkg remove $pkg ;;
2339 !) echo $pkg >> non-free.list ;;
2340 @) DESC="$pkg" ;;
2341 \?) echo -en "$pkg"; read action ;;
2342 esac
2343 done < $3
2345 yes '' | tazlito gen-distro
2346 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2347 mv /etc/tazlito/distro-packages.list.$$ \
2348 /etc/tazlito/distro-packages.list 2>/dev/null
2349 ;;
2352 gen-flavor)
2353 # Generate a new flavor from the last ISO image generated
2354 FLAVOR=${2%.flavor}
2355 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2357 title 'Flavor generation'
2358 check_rootfs
2359 FILES="$FLAVOR.pkglist"
2361 action 'Creating file %s...' "$FLAVOR.flavor"
2362 for i in rootcd rootfs; do
2363 if [ -d "$ADDFILES/$i" ] ; then
2364 FILES="$FILES\n$FLAVOR.$i"
2365 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2366 fi
2367 done
2368 status
2370 answer=$(grep -s ^Description $FLAVOR.desc)
2371 answer=${answer#Description : }
2372 if [ -z "$answer" ]; then
2373 echo -n "Description: "
2374 read answer
2375 fi
2377 action 'Compressing flavor %s...' "$FLAVOR"
2378 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2379 echo "Description : $answer" >> $FLAVOR.desc
2380 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2381 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2382 for i in $(ls $ROOTFS$INSTALLED); do
2383 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2384 EXTRAVERSION=""
2385 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2386 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2387 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2388 echo "$i" >> $FLAVOR.nonfree
2389 else
2390 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2391 fi
2392 done
2393 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2394 for i in $LOCALSTATE/undigest/*/mirror ; do
2395 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2396 done
2397 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2398 touch -t 197001010100.00 $FLAVOR.*
2399 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2400 rm $(echo -e $FILES)
2401 status
2403 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2404 ;;
2407 upgrade-flavor)
2408 # Strip versions from pkglist and update estimated numbers in flavor.desc
2409 flavor="${2%.flavor}"
2410 set -e
2411 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2412 set +e
2414 flv_dir="$(extract_flavor "$flavor")"
2416 strip_versions "$flv_dir/$flavor.pkglist"
2418 action 'Updating %s...' "$flavor.desc"
2420 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2421 set -- $(module calc_sizes "$flv_dir" "$flavor")
2422 restore_mirrors >/dev/null
2424 sed -i -e '/Image is ready/d' \
2425 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2426 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2427 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2428 -e "s|\(Packages *:\).*$|\1 $4|" \
2429 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2430 "$flv_dir/$flavor.desc"
2432 pack_flavor "$flv_dir" "$flavor"
2433 status
2434 display_unknown "$flv_dir/err"
2435 display_warn "$flv_dir/warn"
2436 cleanup
2437 ;;
2440 extract-flavor)
2441 # Extract a flavor into $FLAVORS_REPOSITORY
2442 flavor="${2%.flavor}"
2443 set -e
2444 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2445 set +e
2447 action 'Extracting %s...' "$flavor.flavor"
2448 flv_dir="$(extract_flavor "$flavor" full)"
2449 storage="$FLAVORS_REPOSITORY/$flavor"
2451 rm -rf "$storage" 2>/dev/null
2452 mkdir -p "$storage"
2453 cp -a "$flv_dir"/* "$storage"
2454 rm "$storage/description"
2455 status
2457 strip_versions "$storage/packages.list"
2459 cleanup
2460 ;;
2463 pack-flavor)
2464 # Create a flavor from $FLAVORS_REPOSITORY.
2465 flavor=${2%.flavor}
2466 storage="$FLAVORS_REPOSITORY/$flavor"
2468 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2470 action 'Creating flavor %s...' "$flavor"
2471 tmp_dir="$(mktemp -d)"
2473 while read from to; do
2474 [ -s "$storage/$from" ] || continue
2475 cp -a "$storage/$from" "$tmp_dir/$to"
2476 done <<EOT
2477 mirrors $flavor.mirrors
2478 distro.sh $flavor-distro.sh
2479 receipt $flavor.receipt
2480 non-free.list $flavor.nonfree
2481 EOT
2483 # Build the package list.
2484 # It can include a list from another flavor with the keyword @include
2485 if [ -s "$storage/packages.list" ]; then
2486 include=$(grep '^@include' "$storage/packages.list")
2487 if [ -n "$include" ]; then
2488 include=${include#@include }
2489 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2490 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2491 else
2492 echo -e "\nERROR: Can't find include package list from $include\n"
2493 fi
2494 fi
2495 # Generate the final/initial package list
2496 [ -s "$storage/packages.list" ] && \
2497 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2498 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2499 fi
2501 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2502 # Process multi-rootfs flavor
2503 . "$storage/receipt"
2504 set -- $ROOTFS_SELECTION
2505 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2506 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2507 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2509 for i in rootcd rootfs; do
2510 mkdir "$tmp_dir/$i"
2511 # Copy extra files from the first flavor
2512 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2513 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2514 # Overload extra files by meta flavor
2515 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2516 [ -n "$(ls $tmp_dir/$i)" ] &&
2517 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2518 dogzip "$tmp_dir/$flavor.$i"
2519 rm -rf "$tmp_dir/$i"
2520 done
2521 else
2522 # Process plain flavor
2523 for i in rootcd rootfs; do
2524 [ -d "$storage/$i" ] || continue
2525 (cd "$storage/$i";
2526 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2527 done
2528 fi
2530 unset VERSION MAINTAINER ROOTFS_SELECTION
2531 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2532 ROOTFS_SIZE="$1 (estimated)"
2533 INITRAMFS_SIZE="$2 (estimated)"
2534 ISO_SIZE="$3 (estimated)"
2535 PKGNUM="$4"
2536 . "$storage/receipt"
2538 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2539 Flavor : $FLAVOR
2540 Description : $SHORT_DESC
2541 Version : $VERSION
2542 Maintainer : $MAINTAINER
2543 LiveCD RAM size : $FRUGAL_RAM
2544 Rootfs list : $ROOTFS_SELECTION
2545 Build date : $(date '+%Y%m%d at %T')
2546 Packages : $PKGNUM
2547 Rootfs size : $ROOTFS_SIZE
2548 Initramfs size : $INITRAMFS_SIZE
2549 ISO image size : $ISO_SIZE
2550 ================================================================================
2552 EOT
2554 rm -f $tmp_dir/packages.list
2555 pack_flavor "$tmp_dir" "$flavor"
2556 status
2557 display_unknown "$tmp_dir/err"
2558 display_warn "$flv_dir/warn"
2559 cleanup
2560 ;;
2563 get-flavor)
2564 # Get a flavor's files and prepare for gen-distro.
2565 flavor=${2%.flavor}
2566 title 'Preparing %s distro flavor' "$flavor"
2567 set -e
2568 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2569 set +e
2571 action 'Cleaning %s...' "$DISTRO"
2572 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2573 # Clean old files
2574 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2575 [ -f "$i" ] && rm "$i"
2576 done
2577 mkdir -p "$DISTRO"
2578 status
2580 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2582 action 'Extracting flavor %s...' "$flavor.flavor"
2583 flv_dir="$(extract_flavor "$flavor" info)"
2584 cp -a "$flv_dir"/* .
2585 mv packages.list distro-packages.list
2586 mv -f info /etc/tazlito
2587 status
2589 for i in rootcd rootfs; do
2590 if [ -d "$i" ]; then
2591 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2592 fi
2593 done
2595 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2596 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2598 action 'Updating %s...' 'tazlito.conf'
2599 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2600 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2601 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2602 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2603 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2604 status
2606 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2607 cleanup
2608 ;;
2611 iso2flavor)
2612 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2613 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2615 FLAVOR=${3%.flavor}
2616 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2617 mount -o loop,ro $2 $TMP_DIR/iso
2618 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2619 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2620 ! -s $TMP_DIR/flavor/*.desc ]; then
2621 _ 'META flavors are not supported.'
2622 umount -d $TMP_DIR/iso
2623 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2624 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2625 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2626 umount -d $TMP_DIR/iso
2627 else
2628 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2629 uncompress $i | \
2630 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2631 done
2632 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2633 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2634 '/etc/slitaz-release' '/boot/rootfs.gz'
2635 umount -d $TMP_DIR/iso
2636 else
2637 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2638 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2639 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2640 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2641 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2642 umount -d $TMP_DIR/iso
2643 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2644 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2645 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2646 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2647 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2648 < $TMP_DIR/rootfs$INSTALLED.md5
2649 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2650 if [ -s $TMP_DIR/flavor/*desc ]; then
2651 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2652 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2653 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2654 for i in rootfs rootcd ; do
2655 [ -s $TMP_DIR/flavor/*.list$i ] &&
2656 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2657 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2658 done
2659 else
2660 find_flavor_rootfs $TMP_DIR/rootfs
2661 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2662 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2663 for i in rootfs rootcd ; do
2664 [ "$(ls $TMP_DIR/$i)" ] &&
2665 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2666 done
2667 unset VERSION MAINTAINER
2668 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2669 if [ -n "$DESCRIPTION" ]; then
2670 _n 'Flavor version : '; read -t 30 VERSION
2671 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2672 fi
2674 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2675 Flavor : $FLAVOR
2676 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2677 Version : ${VERSION:-1.0}
2678 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2679 LiveCD RAM size : $RAM_SIZE
2680 Build date : $BUILD_DATE
2681 Packages : $PKGCNT
2682 Rootfs size : $ROOTFS_SIZE
2683 Initramfs size : $INITRAMFS_SIZE
2684 ISO image size : $ISO_SIZE
2685 ================================================================================
2687 EOT
2688 longline "Tazlito can't detect each file installed during \
2689 a package post_install. You should extract this flavor (tazlito extract-flavor \
2690 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2691 tree and remove files generated by post_installs.
2692 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2693 repack the flavor (tazlito pack-flavor $FLAVOR)"
2694 fi
2695 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2696 fi
2697 fi
2698 rm -rf $TMP_DIR
2699 ;;
2702 gen-distro)
2703 # Generate a live distro tree with a set of packages.
2705 check_root
2706 start_time=$(date +%s)
2708 # Tazlito options: --iso or --cdrom
2709 CDROM=''
2710 [ -n "$iso" ] && CDROM="-o loop $iso"
2711 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2713 # Check if a package list was specified on cmdline.
2714 if [ -f "$2" ]; then
2715 LIST_NAME="$2"
2716 else
2717 LIST_NAME='distro-packages.list'
2718 fi
2720 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2721 'Please clean the distro tree or change directory path.'
2722 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2723 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2725 # If list not given: build list with all installed packages
2726 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2727 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2728 fi
2730 # Exit if no list name.
2731 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2733 # Start generation.
2734 title 'Tazlito generating a distro'
2736 # Misc checks
2737 mkdir -p "$PACKAGES_REPOSITORY"
2738 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2739 newline
2741 # Mount CD-ROM to be able to repack boot-loader packages
2742 if [ ! -e /boot -a -n "$CDROM" ]; then
2743 mkdir $TMP_MNT
2744 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2745 ln -s "$TMP_MNT/boot" /
2746 if [ ! -d "$ADDFILES/rootcd" ] ; then
2747 mkdir -p "$ADDFILES/rootcd"
2748 for i in $(ls $TMP_MNT); do
2749 [ "$i" = 'boot' ] && continue
2750 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2751 done
2752 fi
2753 else
2754 rmdir "$TMP_MNT"
2755 fi
2756 fi
2758 # Rootfs stuff.
2759 echo 'Preparing the rootfs directory...'
2760 mkdir -p "$ROOTFS"
2761 export root="$ROOTFS"
2762 # pass current 'mirror' to the root
2763 mkdir -p $root/var/lib/tazpkg $root/etc
2764 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2765 cp -f /etc/slitaz-release $root/etc/slitaz-release
2766 strip_versions "$LIST_NAME"
2768 if [ "$REPACK" = 'y' ]; then
2769 # Determine full packages list with all dependencies
2770 tmp_dir="$(mktemp -d)"
2771 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2772 touch "$tmp_dir/full.pkglist"
2773 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2775 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2776 while read pkgname pkgver; do
2777 # Is package in full list?
2778 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2779 # Is package already repacked?
2780 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2781 _ 'Repacking %s...' "$pkgname-$pkgver"
2782 tazpkg repack "$pkgname" --quiet
2783 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2784 status
2785 done
2787 rm -r "$tmp_dir"
2788 fi
2790 if [ -f non-free.list ]; then
2791 # FIXME: working in the ROOTFS chroot?
2792 newline
2793 echo 'Preparing non-free packages...'
2794 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2795 while read pkg ; do
2796 if [ ! -d "$INSTALLED/$pkg" ]; then
2797 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2798 tazpkg get-install get-$pkg
2799 fi
2800 get-$pkg "$ROOTFS"
2801 fi
2802 tazpkg repack $pkg
2803 pkg=$(ls $pkg*.tazpkg)
2804 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2805 mv $pkg $PACKAGES_REPOSITORY
2806 done < non-free.list
2807 fi
2808 cp $LIST_NAME $DISTRO/distro-packages.list
2809 newline
2811 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2813 cd $DISTRO
2814 cp distro-packages.list $ROOTFS/etc/tazlito
2815 # Copy all files from $ADDFILES/rootfs to the rootfs.
2816 if [ -d "$ADDFILES/rootfs" ] ; then
2817 action 'Copying addfiles content to the rootfs...'
2818 cp -a $ADDFILES/rootfs/* $ROOTFS
2819 status
2820 fi
2822 action 'Root filesystem is generated...'; status
2824 # Root CD part.
2825 action 'Preparing the rootcd directory...'
2826 mkdir -p $ROOTCD
2827 status
2829 # Move the boot dir with the Linux kernel from rootfs.
2830 # The efi & boot dirs go directly on the CD.
2831 if [ -d "$ROOTFS/efi" ] ; then
2832 action 'Moving the efi directory...'
2833 mv $ROOTFS/efi $ROOTCD
2834 status
2835 fi
2836 if [ -d "$ROOTFS/boot" ] ; then
2837 action 'Moving the boot directory...'
2838 mv $ROOTFS/boot $ROOTCD
2839 status
2840 fi
2841 cd $DISTRO
2842 # Copy all files from $ADDFILES/rootcd to the rootcd.
2843 if [ -d "$ADDFILES/rootcd" ] ; then
2844 action 'Copying addfiles content to the rootcd...'
2845 cp -a $ADDFILES/rootcd/* $ROOTCD
2846 status
2847 fi
2848 # Execute the distro script used to perform tasks in the rootfs
2849 # before compression. Give rootfs path in arg
2850 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2851 if [ -x "$DISTRO_SCRIPT" ]; then
2852 echo 'Executing distro script...'
2853 sh $DISTRO_SCRIPT $DISTRO
2854 fi
2856 # Execute the custom_rules() found in receipt.
2857 if [ -s "$TOP_DIR/receipt" ]; then
2858 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2859 echo -e "Executing: custom_rules()\n"
2860 . "$TOP_DIR/receipt"
2861 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2862 fi
2863 fi
2865 # Multi-rootfs
2866 if [ -s /etc/tazlito/rootfs.list ]; then
2868 FLAVOR_LIST="$(awk '{
2869 for (i = 2; i <= NF; i+=2)
2870 printf "%s ", $i;
2871 }' /etc/tazlito/rootfs.list)"
2873 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2874 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2875 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2877 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2878 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2879 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2880 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2882 n=0
2883 last=$ROOTFS
2884 while read flavor; do
2885 n=$(($n+1))
2886 mkdir ${ROOTFS}0$n
2887 export root="${ROOTFS}0$n"
2888 # initial tazpkg setup in empty rootfs
2889 tazpkg --root=$root >/dev/null 2>&1
2891 newline
2892 boldify "Building $flavor rootfs..."
2894 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2895 cp "$TOP_DIR/$flavor.flavor" .
2897 if [ ! -s "$flavor.flavor" ]; then
2898 # We may have it in $FLAVORS_REPOSITORY
2899 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2900 tazlito pack-flavor $flavor
2901 else
2902 download $flavor.flavor
2903 fi
2904 fi
2906 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2907 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2908 cp $flavor.pkglist $DISTRO/list-packages0$n
2909 status
2911 strip_versions "$DISTRO/list-packages0$n"
2913 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2915 action 'Updating the boot directory...'
2916 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2917 rm -rf ${ROOTFS}0$n/boot
2919 cd $DISTRO
2920 if [ -s $flavor.rootfs ]; then
2921 _n 'Adding %s rootfs extra files...' "$flavor"
2922 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2923 fi
2925 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2926 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2927 status
2929 rm -f $flavor.flavor install-list
2930 mergefs ${ROOTFS}0$n $last
2931 last=${ROOTFS}0$n
2932 done <<EOT
2933 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2934 EOT
2935 #'
2936 i=$(($n+1))
2937 while [ $n -gt 0 ]; do
2938 mv ${ROOTFS}0$n ${ROOTFS}$i
2939 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2940 gen_initramfs ${ROOTFS}$i
2941 n=$(($n-1))
2942 i=$(($i-1))
2943 export LZMA_HISTORY_BITS=26
2944 done
2945 mv $ROOTFS ${ROOTFS}$i
2946 gen_initramfs ${ROOTFS}$i
2947 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2948 ROOTFS=${ROOTFS}1
2949 else
2950 # Initramfs and ISO image stuff.
2951 gen_initramfs $ROOTFS
2952 fi
2953 gen_livecd_isolinux
2954 distro_stats
2955 cleanup
2956 ;;
2959 clean-distro)
2960 # Remove old distro tree.
2962 check_root
2963 title 'Cleaning: %s' "$DISTRO"
2964 if [ -d "$DISTRO" ] ; then
2965 if [ -d "$ROOTFS" ] ; then
2966 action 'Removing the rootfs...'
2967 rm -f $DISTRO/$INITRAMFS
2968 rm -rf $ROOTFS
2969 status
2970 fi
2971 if [ -d "$ROOTCD" ] ; then
2972 action 'Removing the rootcd...'
2973 rm -rf $ROOTCD
2974 status
2975 fi
2976 action 'Removing eventual ISO image...'
2977 rm -f $DISTRO/$ISO_NAME.iso
2978 rm -f $DISTRO/$ISO_NAME.md5
2979 status
2980 fi
2981 footer
2982 ;;
2985 check-distro)
2986 # Check for a few LiveCD needed files not installed by packages.
2988 # TODO: Remove this function.
2989 # First two files are maintained by tazpkg while it runs on rootfs,
2990 # while last one file should be maintained by tazlito itself.
2991 check_rootfs
2992 title 'Checking distro: %s' "$ROOTFS"
2993 # SliTaz release info.
2994 rel='/etc/slitaz-release'
2995 if [ ! -f "$ROOTFS$rel" ]; then
2996 _ 'Missing release info: %s' "$rel"
2997 else
2998 action 'Release : %s' "$(cat $ROOTFS$rel)"
2999 status
3000 fi
3001 # Tazpkg mirror.
3002 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
3003 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
3004 todomsg
3005 else
3006 action 'Mirror configuration exists...'
3007 status
3008 fi
3009 # Isolinux msg
3010 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
3011 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
3012 todomsg
3013 else
3014 action 'Isolinux message seems good...'
3015 status
3016 fi
3017 footer
3018 ;;
3021 writeiso)
3022 # Writefs to ISO image including /home unlike gen-distro we don't use
3023 # packages to generate a rootfs, we build a compressed rootfs with all
3024 # the current filesystem similar to 'tazusb writefs'.
3026 DISTRO='/home/slitaz/distro'
3027 ROOTCD="$DISTRO/rootcd"
3028 COMPRESSION="${2:-none}"
3029 ISO_NAME="${3:-slitaz}"
3030 check_root
3031 # Start info
3032 title 'Write filesystem to ISO'
3033 longline "The command writeiso will write the current filesystem into a \
3034 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3035 newline
3036 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3038 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3039 # Save some space
3040 rm -rf /var/cache/tazpkg/*
3041 rm -f /var/lib/tazpkg/*.bak
3042 rm -rf $DISTRO
3044 # Optionally remove sound card selection and screen resolution.
3045 if [ -z $LaunchedByTazpanel ]; then
3046 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3047 case $anser in
3048 y)
3049 action 'Removing current sound card and screen configurations...'
3050 rm -f /var/lib/sound-card-driver
3051 rm -f /var/lib/alsa/asound.state
3052 rm -f /etc/X11/xorg.conf ;;
3053 *)
3054 action 'Keeping current sound card and screen configurations...' ;;
3055 esac
3056 status
3057 newline
3059 # Optionally remove i18n settings
3060 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3061 case $anser in
3062 y)
3063 action 'Removing current locale/keymap settings...'
3064 newline > /etc/locale.conf
3065 newline > /etc/keymap.conf ;;
3066 *)
3067 action 'Keeping current locale/keymap settings...' ;;
3068 esac
3069 status
3070 fi
3072 # Clean-up files by default
3073 newline > /etc/udev/rules.d/70-persistent-net.rules
3074 newline > /etc/udev/rules.d/70-persistant-cd.rules
3076 # Create list of files including default user files since it is defined in /etc/passwd
3077 # and some new users might have been added.
3078 cd /
3079 echo 'init' > /tmp/list
3080 for dir in bin etc sbin var dev lib root usr home opt; do
3081 [ -d $dir ] && find $dir
3082 done >> /tmp/list
3084 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3085 [ -d $dir ] && echo $dir
3086 done >> /tmp/list
3088 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3090 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3091 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3092 #fi
3093 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3094 touch /var/log/wtmp
3096 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3097 sed -i "/var\/log\/$removelog/d" /tmp/list
3098 done
3100 # Generate initramfs with specified compression and display rootfs
3101 # size in realtime.
3102 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3104 write_initramfs &
3105 sleep 2
3106 cd - > /dev/null
3107 echo -en "\nFilesystem size:"
3108 while [ ! -f /tmp/rootfs ]; do
3109 sleep 1
3110 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3111 done
3112 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3113 echo -e "\n"
3114 rm -f /tmp/rootfs
3116 # Move freshly generated rootfs to the cdrom.
3117 mkdir -p $ROOTCD/boot
3118 mv -f /$INITRAMFS $ROOTCD/boot
3119 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3121 # Now we need the kernel and isolinux files.
3122 copy_from_cd() {
3123 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3124 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3125 unmeta_boot $ROOTCD
3126 umount /media/cdrom
3129 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3130 copy_from_cd;
3131 elif mount | grep /media/cdrom; then
3132 copy_from_cd;
3133 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3134 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3135 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3136 else
3137 touch /tmp/.write-iso-error
3138 longline "When SliTaz is running in RAM the kernel and bootloader \
3139 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3140 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3141 echo -en "----\nENTER to continue..."; read i
3142 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3143 copy_from_cd
3144 fi
3146 # Generate the iso image.
3147 touch /tmp/.write-iso
3148 newline
3149 cd $DISTRO
3150 create_iso $ISO_NAME.iso $ROOTCD
3151 action 'Creating the ISO md5sum...'
3152 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3153 status
3155 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3156 rm -f /tmp/.write-iso
3158 if [ -z $LaunchedByTazpanel ]; then
3159 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3160 case $anser in
3161 y)
3162 umount /dev/cdrom 2>/dev/null
3163 eject
3164 echo -n "Please insert a blank CD-ROM and press ENTER..."
3165 read i && sleep 2
3166 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3167 echo -en "----\nENTER to continue..."; read i ;;
3168 *)
3169 exit 0 ;;
3170 esac
3171 fi
3172 ;;
3175 burn-iso)
3176 # Guess CD-ROM device, ask user and burn the ISO.
3178 check_root
3179 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3180 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3181 # We can specify an alternative ISO from the cmdline.
3182 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3183 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3185 title 'Tazlito burn ISO'
3186 echo "CD-ROM device : /dev/$DRIVE_NAME"
3187 echo "Drive speed : $DRIVE_SPEED"
3188 echo "ISO image : $iso"
3189 footer
3191 case $(yesorno 'Burn ISO image?' 'n') in
3192 y)
3193 title 'Starting Wodim to burn the ISO...'
3194 sleep 2
3195 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3196 footer 'ISO image is burned to CD-ROM.'
3197 ;;
3198 *)
3199 die 'Exiting. No ISO burned.'
3200 ;;
3201 esac
3202 ;;
3205 merge)
3206 # Merge multiple rootfs into one iso.
3208 if [ -z "$2" ]; then
3209 cat <<EOT
3210 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3212 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3213 i.e: rootfsN is a subset of rootfsN-1
3214 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3215 The boot loader will select the rootfs according to the RAM size detected.
3217 Example:
3218 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3220 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3221 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3223 EOT
3224 exit 2
3225 fi
3227 shift # skip merge
3228 append="$1 slitaz1"
3229 shift # skip size1
3230 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3232 ISO=$1.merged
3234 # Extract filesystems
3235 action 'Mounting %s' "$1"
3236 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3237 status || cleanup_merge
3239 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3240 make_bzImage_hardlink $TMP_DIR/iso/boot
3241 umount -d $TMP_DIR/mnt
3242 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3243 _ '%s is already a merged iso. Aborting.' "$1"
3244 cleanup_merge
3245 fi
3246 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3247 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3248 if [ ! -f /boot/isolinux/ifmem.c32 -a
3249 ! -f /boot/isolinux/c32box.c32 ]; then
3250 cat <<EOT
3251 No file /boot/isolinux/ifmem.c32
3252 Please install syslinux package !
3253 EOT
3254 rm -rf $TMP_DIR
3255 exit 1
3256 fi
3257 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3258 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3259 fi
3261 action 'Extracting %s' 'iso/rootfs.gz'
3262 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3263 [ -d $TMP_DIR/rootfs1/etc ]
3264 status || cleanup_merge
3266 n=1
3267 while [ -n "$2" ]; do
3268 shift # skip rootfs N-1
3269 p=$n
3270 n=$(($n + 1))
3271 append="$append $1 slitaz$n"
3272 shift # skip size N
3273 mkdir -p $TMP_DIR/rootfs$n
3275 action 'Extracting %s' "$1"
3276 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3277 [ -d "$TMP_DIR/rootfs$n/etc" ]
3278 status || cleanup_merge
3280 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3281 action 'Creating %s' "rootfs$p.gz"
3282 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3283 status
3284 done
3285 action 'Creating %s' "rootfs$n.gz"
3286 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3287 status
3288 rm -f $TMP_DIR/iso/boot/rootfs.gz
3289 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3290 create_iso $ISO $TMP_DIR/iso
3291 rm -rf $TMP_DIR
3292 ;;
3295 repack)
3296 # Repack an iso with maximum lzma compression ratio.
3298 ISO=$2
3299 mkdir -p $TMP_DIR/mnt
3301 # Extract filesystems
3302 action 'Mounting %s' "$ISO"
3303 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3304 status || cleanup_merge
3306 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3307 umount -d $TMP_DIR/mnt
3309 for i in $TMP_DIR/iso/boot/rootfs* ; do
3310 action 'Repacking %s' "$(basename $i)"
3311 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3312 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3313 align_to_32bits $i
3314 status
3315 done
3317 create_iso $ISO $TMP_DIR/iso
3318 rm -rf $TMP_DIR
3319 ;;
3322 build-loram)
3323 # Build a Live CD for low RAM systems.
3325 ISO="$2"
3326 OUTPUT="$3"
3327 [ -z "$3" ] && \
3328 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3329 mkdir -p "$TMP_DIR/iso"
3330 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3331 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3332 if ! check_iso_for_loram ; then
3333 umount -d "$TMP_DIR/iso"
3334 die "$ISO is not a valid SliTaz live CD. Abort."
3335 fi
3336 case "$4" in
3337 cdrom) build_loram_cdrom ;;
3338 http) build_loram_http ;;
3339 *) build_loram_ram "$5" ;;
3340 esac
3341 umount $TMP_DIR/iso # no -d: needs /proc
3342 losetup -d $loopdev
3343 rm -rf $TMP_DIR
3344 ;;
3347 emu-iso)
3348 # Emulate an ISO image with Qemu.
3349 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3350 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3351 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3352 echo -e "\nStarting Qemu emulator:\n"
3353 echo -e "qemu $QEMU_OPTS $iso\n"
3354 qemu $QEMU_OPTS $iso
3355 ;;
3358 deduplicate)
3359 # Deduplicate files in a tree
3360 shift
3361 deduplicate "$@"
3362 ;;
3365 usage|*)
3366 # Print usage also for all unknown commands.
3367 usage
3368 ;;
3369 esac
3371 exit 0