tazlito view tazlito @ rev 512

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