tazlito view tazlito @ rev 510

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