tazlito view tazlito @ rev 528

tazlito update README & index.html year
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Oct 04 13:26:53 2020 +0000 (2020-10-04)
parents df946fc43fb0
children 8654e61dc1b3
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$(sed '/bzImage/!d;s|.*root=[^ ]*||;q' $basedir/boot/isolinux/isolinux.cfg)\
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 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
554 if [ "$ftype" = "33 32" ]; then
555 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
556 conv=notrunc
557 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
558 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
559 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
560 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
561 0 80 00 29 00 00 00 00 $doslabel |
562 0 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
563 EOT
564 while read ofs data; do
565 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
566 bs=1 seek=$ofs of=$basedir/boot/isolinux/efi.img
567 done <<EOT
568 510 55:aa:52:52:61:41
569 996 72:72:41:61:ff:ff:ff:ff:02
570 1022 55:aa
571 EOT
572 else
573 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
574 seek=510 bs=1 conv=notrunc
575 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
576 conv=notrunc
577 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
578 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
579 0 $size32 80 00 29 00 00 00 00 $doslabel |
580 0 46 41 54 $ftype 20 20 20 cd 18 |
581 0 cd 19 eb fa |
582 EOT
583 fi 2> /dev/null
585 # Create fats
586 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
587 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
588 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
589 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
591 # Add label
592 echo "0 $doslabel 08 |" | hexdump -R | \
593 dd of=$basedir/boot/isolinux/efi.img bs=512 conv=notrunc \
594 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
596 mkdir -p /tmp/mnt$$
597 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
598 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
599 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
600 sync
601 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
602 skip=$rsect bs=512 count=$fsect 2> /dev/null
603 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
604 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
605 umount /tmp/mnt$$
606 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
607 seek=$rsect bs=512 conv=notrunc 2> /dev/null
608 rm /tmp/fat$$
609 rmdir /tmp/mnt$$
611 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
612 seek=$count 2> /dev/null
613 }
616 # isolinux.conf doesn't know the kernel version.
617 # We name the kernel image 'bzImage'.
618 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
620 make_bzImage_hardlink() {
621 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
622 rm -f ${1:-.}/bzImage 2>/dev/null
623 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
624 fi
625 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
626 rm -f ${1:-.}/bzImage64 2> /dev/null
627 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
628 fi
629 }
632 create_iso() {
633 cd $2
634 deduplicate
635 sed -i "s|20[1-9][0-9]|$(date +%Y)|" $2/README $2/index.html
637 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
638 make_bzImage_hardlink $2/boot
639 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
641 while read file; do ls -r $file 2> /dev/null; done << EOT | \
642 awk 'BEGIN { n=100 } { print $1 " " n-- }' > /tmp/cdsort$$
643 $PWD/boot/isolinux/boot.cat
644 $PWD/boot/isolinux/isolinux.bin
645 $PWD/boot/isolinux/isolinux.cfg
646 $PWD/boot/isolinux/vesamenu.c32
647 $PWD/boot/isolinux/splash.*g
648 $PWD/boot/isolinux/i18n.cfg
649 $PWD/boot/isolinux/c32box.c32
650 $PWD/boot/isolinux/kbd
651 $PWD/boot/isolinux/efi.img
652 $PWD/boot/bzImage*
653 $PWD/efi/boot/linux.cmdline*
654 $PWD/boot/rootfs*
655 EOT
657 action 'Computing md5...'
658 touch $2/boot/isolinux/boot.cat
659 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
660 sort -k 2 > md5sum
661 status
663 cd - >/dev/null
664 title 'Generating ISO image'
666 _ 'Generating %s' "$1"
667 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
668 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
669 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
670 -no-emul-boot -boot-load-size 4 -boot-info-table \
671 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
672 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
673 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
674 -A "tazlito $VERSION/$(genisoimage --version)" \
675 -copyright README -P "www.slitaz.org" -no-pad $2
676 rm -f /tmp/cdsort$$
677 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
679 mkdir /tmp/mnt$$
680 mount -o loop,ro $1 /tmp/mnt$$
681 fixup_uefi_part $1 /tmp/mnt$$
682 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
683 ${uefi:+boot/isolinux/efi.img} ; do
684 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
685 done
686 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
687 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
688 umount -d /tmp/mnt$$
689 rmdir /tmp/mnt$$
691 if [ -s '/etc/tazlito/info' ]; then
692 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
693 action 'Storing ISO info...'
694 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
695 status
696 fi
697 fi
699 if [ -x '/usr/bin/isohybrid' ]; then
700 action 'Creating hybrid ISO...'
701 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
702 status
703 fi
705 if [ -x '/usr/bin/iso2exe' ]; then
706 echo 'Creating EXE header...'
707 /usr/bin/iso2exe $1 2>/dev/null
708 fi
709 }
712 # Generate a new ISO image using isolinux.
714 gen_livecd_isolinux() {
715 # Some packages may want to alter iso
716 genisohooks iso
717 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
719 # Set date for boot msg.
720 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
721 DATE=$(date +%Y%m%d)
722 action 'Setting build date to: %s...' "$DATE"
723 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
724 status
725 fi
727 cd $DISTRO
728 create_iso $ISO_NAME.iso $ROOTCD
730 action 'Creating the ISO md5sum...'
731 md5sum $ISO_NAME.iso > $ISO_NAME.md5
732 status
734 separator
735 # Some packages may want to alter final iso
736 genisohooks final
737 }
740 lzma_history_bits() {
741 #
742 # This generates an ISO which boots with Qemu but gives
743 # rootfs errors in frugal or liveUSB mode.
744 #
745 # local n
746 # local sz
747 # n=20 # 1Mb
748 # sz=$(du -sk $1 | cut -f1)
749 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
750 # n=$(( $n + 1 ))
751 # sz=$(( $sz / 2 ))
752 # done
753 # echo $n
754 echo ${LZMA_HISTORY_BITS:-24}
755 }
758 lzma_switches() {
759 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
760 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
761 }
764 lzma_set_size() {
765 # Update size field for lzma'd file packed using -si switch
766 return # Need to fix kernel code?
768 local n i
769 n=$(unlzma < $1 | wc -c)
770 for i in $(seq 1 8); do
771 printf '\\\\x%02X' $(($n & 255))
772 n=$(($n >> 8))
773 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
774 }
777 align_to_32bits() {
778 local size=$(stat -c %s ${1:-/dev/null})
779 [ $((${size:-0} & 3)) -ne 0 ] &&
780 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
781 }
784 dolz4() {
785 [ "$(which lz4)" ] || tazpkg get-install lz4
786 lz4 -9 > $1
787 }
790 dogzip() {
791 gzip -9 > $1
792 [ -x /usr/bin/advdef ] && advdef -qz4 $1
793 }
796 # Pack rootfs
798 pack_rootfs() {
799 ( cd $1; find . -print | cpio -o -H newc ) | \
800 case "$COMPRESSION" in
801 none)
802 _ 'Creating %s without compression...' 'initramfs'
803 cat > $2
804 ;;
805 lz4)
806 _ 'Creating %s with lz4 compression...' 'initramfs'
807 dolz4 $2
808 ;;
809 gzip)
810 _ 'Creating %s with gzip compression...' 'initramfs'
811 dogzip $2
812 ;;
813 *)
814 _ 'Creating %s with lzma compression...' 'initramfs'
815 lzma e -si -so $(lzma_switches $1) > $2
816 lzma_set_size $2
817 ;;
818 esac
819 align_to_32bits $2
820 echo 1 > /tmp/rootfs
821 }
824 # Compression functions for writeiso.
826 write_initramfs() {
827 case "$COMPRESSION" in
828 lzma)
829 _n 'Creating %s with lzma compression...' "$INITRAMFS"
830 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
831 align='y'
832 lzma_set_size "/$INITRAMFS"
833 ;;
834 gzip)
835 _ 'Creating %s with gzip compression...' "$INITRAMFS"
836 cpio -o -H newc | dogzip "/$INITRAMFS"
837 ;;
838 lz4)
839 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
840 cpio -o -H newc | dolz4 "/$INITRAMFS"
841 ;;
842 *)
843 # align='y'
844 _ 'Creating %s without compression...' "$INITRAMFS"
845 cpio -o -H newc > "/$INITRAMFS"
846 ;;
847 esac < /tmp/list
848 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
849 echo 1 > /tmp/rootfs
850 }
853 # Deduplicate files (MUST be on the same filesystem).
855 deduplicate() {
856 find "${@:-.}" -xdev -type f ! -type l -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
857 (
858 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""; hinode=""
859 while read attr inode link file; do
860 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ] &&
861 { [ "$inode" = "$hinode" ] || cmp "$file" "$old_file" >/dev/null 2>&1; } ; then
862 rm -f "$file"
863 if ln "$old_file" "$file" 2>/dev/null; then
864 hinode="$inode"
865 inode="$old_inode"
866 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
867 save="$(($save+(${attr%%-*}+512)/1024))"
868 continue
869 else
870 cp -p "$old_file" "$file"
871 fi
872 else
873 hinode=""
874 fi
875 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
876 done
877 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
878 )
880 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
881 while read attr inode link file; do
882 echo "$attr-$(readlink "$file" | uuencode -m - | \
883 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
884 done | sort | \
885 (
886 old_attr=""; hardlinks=0;
887 while read attr inode link file; do
888 if [ "$attr" = "$old_attr" ]; then
889 if [ "$inode" != "$old_inode" ]; then
890 rm -f "$file"
891 if ln "$old_file" "$file" 2>/dev/null; then
892 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
893 else
894 cp -a "$old_file" "$file"
895 fi
896 fi
897 else
898 old_file="$file"
899 old_attr="$attr"
900 old_inode="$inode"
901 fi
902 done
903 _ '%s duplicate symlinks.' "$hardlinks"
904 )
905 }
908 # Generate a new initramfs from the root filesystem.
910 gen_initramfs() {
911 # Just in case CTRL+c
912 rm -f $DISTRO/gen
914 # Some packages may want to alter rootfs
915 genisohooks rootfs
916 cd $1
918 # Normalize file time
919 find $1 -newer $1 -exec touch -hr $1 {} \;
921 # Link duplicate files
922 deduplicate
924 # Use lzma if installed. Display rootfs size in realtime.
925 rm -f /tmp/rootfs 2>/dev/null
926 pack_rootfs . $DISTRO/$(basename $1).gz &
927 sleep 2
928 echo -en "\nFilesystem size:"
929 while [ ! -f /tmp/rootfs ]; do
930 sleep 1
931 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
932 done
933 echo -e "\n"
934 rm -f /tmp/rootfs
935 cd $DISTRO
936 mv $(basename $1).gz $ROOTCD/boot
937 }
940 distro_sizes() {
941 if [ -n "$start_time" ]; then
942 time=$(($(date +%s) - $start_time))
943 sec=$time
944 div=$(( ($time + 30) / 60))
945 [ "$div" -ne 0 ] && min="~ ${div}m"
946 _ 'Build time : %ss %s' "$sec" "$min"
947 fi
948 cat <<EOT
949 Build date : $(date +%Y%m%d)
950 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
951 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
952 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
953 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
954 EOT
955 footer "Image is ready: $ISO_NAME.iso"
956 }
959 # Print ISO and rootfs size.
961 distro_stats() {
962 title 'Distro statistics: %s' "$DISTRO"
963 distro_sizes
964 }
967 # Create an empty configuration file.
969 empty_config_file() {
970 cat >> tazlito.conf <<"EOF"
971 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
972 #
974 # Name of the ISO image to generate.
975 ISO_NAME=""
977 # ISO image volume name.
978 VOLUM_NAME="SliTaz"
980 # Name of the preparer.
981 PREPARED="$USER"
983 # Path to the packages repository and the packages.list.
984 PACKAGES_REPOSITORY=""
986 # Path to the distro tree to gen-distro from a list of packages.
987 DISTRO=""
989 # Path to the directory containing additional files
990 # to copy into the rootfs and rootcd of the LiveCD.
991 ADDFILES="$DISTRO/addfiles"
993 # Default answer for binary question (Y or N)
994 DEFAULT_ANSWER="ASK"
996 # Compression utility (lzma, gzip or none)
997 COMPRESSION="lzma"
998 EOF
999 }
1002 # Extract rootfs.gz somewhere
1004 extract_rootfs() {
1005 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
1006 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
1007 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1008 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1009 (cd "$2"; cpio -idm --quiet 2>/dev/null < "$1")
1013 # Extract flavor file to temp directory
1015 extract_flavor() {
1016 # Input: $1 - flavor name to extract;
1017 # $2 = absent/empty: just extract 'outer layer'
1018 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1019 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1020 # Output: temp dir path where flavor was extracted
1021 local f="$1.flavor" from to infos="$1.desc"
1022 [ -f "$f" ] || die "File '$f' not found"
1023 local dir="$(mktemp -d)"
1024 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1026 if [ -n "$2" ]; then
1027 cd $dir
1029 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1031 for i in rootcd rootfs; do
1032 [ -f "$1.$i" ] || continue
1033 mkdir "$i"
1034 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1035 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1036 rm "$1.$i"
1037 done
1038 touch -t 197001010100.00 $1.*
1039 # Info to be stored inside ISO
1040 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1041 rm $1.list*
1043 # Renames
1044 while read from to; do
1045 [ -f "$from" ] || continue
1046 mv "$from" "$to"
1047 done <<EOT
1048 $1.nonfree non-free.list
1049 $1.pkglist packages.list
1050 $1-distro.sh distro.sh
1051 $1.receipt receipt
1052 $1.mirrors mirrors
1053 $1.desc description
1054 EOT
1055 fi
1057 echo $dir
1061 # Pack flavor file from temp directory
1063 pack_flavor() {
1064 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1068 # Remove duplicate files
1070 files_match() {
1071 if [ -d "$1" ]; then
1072 return 1
1074 elif [ -L "$1" ] && [ -L "$2" ]; then
1075 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1077 elif [ -f "$1" ] && [ -f "$2" ]; then
1078 cmp -s "$1" "$2" && return 0
1080 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1081 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1082 return 0
1084 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1085 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1086 return 0
1088 fi 2> /dev/null
1089 return 1
1092 remove_with_path() {
1093 dir="$(dirname $1)"
1094 rm -f "$1"
1095 while rmdir "$dir" 2> /dev/null; do
1096 dir="$(dirname $dir)"
1097 done
1100 mergefs() {
1101 # Note, many packages have files with spaces in the name
1102 IFS=$'\n'
1104 local size1=$(du -hs "$1" | awk '{ print $1 }')
1105 local size2=$(du -hs "$2" | awk '{ print $1 }')
1106 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1108 # merge symlinks files and devices
1109 ( cd "$1"; find ) | \
1110 while read file; do
1111 files_match "$1/$file" "$2/$file" "$file" &&
1112 remove_with_path "$2/$file"
1113 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1114 done
1116 unset IFS
1117 status
1121 cleanup_merge() {
1122 rm -rf $TMP_DIR
1123 exit 1
1127 # Update isolinux config files for multiple rootfs
1129 update_bootconfig() {
1130 local files
1131 action 'Updating boot config files...'
1132 files="$(grep -l 'include common' $1/*.cfg)"
1133 for file in $files; do
1134 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1135 if (/label/) label=$0;
1136 else if (/kernel/) kernel=$0;
1137 else if (/append/) {
1138 i=index($0,"rootfs.gz");
1139 append=substr($0,i+9);
1141 else if (/include/) {
1142 for (i = 1; i <= n; i++) {
1143 print label i
1144 print kernel;
1145 initrd="initrd=/boot/rootfs" n ".gz"
1146 for (j = n - 1; j >= i; j--) {
1147 initrd=initrd ",/boot/rootfs" j ".gz";
1149 printf "\tappend %s%s\n",initrd,append;
1150 print "";
1152 print;
1154 else print;
1155 }' < $file > $file.$$
1156 mv -f $file.$$ $file
1157 done
1158 sel="$(echo $2 | awk '{
1159 for (i=1; i<=NF; i++)
1160 if (i % 2 == 0) printf " slitaz%d", i/2
1161 else printf " %s", $i
1162 }')"
1164 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1166 label slitaz
1167 kernel /boot/isolinux/ifmem.c32
1168 append$sel noram
1170 label noram
1171 config noram.cfg
1173 EOT
1175 # Update vesamenu
1176 if [ -s "$1/isolinux.cfg" ]; then
1177 files="$files $1/isolinux.cfg"
1178 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1179 BEGIN {
1180 kernel = " COM32 c32box.c32"
1183 if (/ROWS/) print "MENU ROWS " n+$3;
1184 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1185 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1186 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1187 else if (/VSHIFT/) {
1188 x = $3-n;
1189 if (x < 0) x = 0;
1190 print "MENU VSHIFT " x;
1192 else if (/rootfs.gz/) {
1193 linux = "";
1194 if (/bzImage/) linux = "linux /boot/bzImage ";
1195 i = index($0, "rootfs.gz");
1196 append = substr($0, i+9);
1197 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1198 printf "\tappend%s noram\n", sel;
1199 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1200 for (i = 1; i <= n; i++) {
1201 print "LABEL slitaz" i
1202 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1203 printf "%s\n", kernel;
1204 initrd = "initrd=/boot/rootfs" n ".gz"
1205 for (j = n - 1; j >= i; j--) {
1206 initrd = initrd ",/boot/rootfs" j ".gz";
1208 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1211 else if (/bzImage/) kernel = $0;
1212 else print;
1213 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1214 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1215 fi
1217 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1218 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1219 cat > $1/noram.cfg <<EOT
1220 implicit 0
1221 prompt 1
1222 timeout 80
1223 $(grep '^F[0-9]' $1/isolinux.cfg)
1225 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1226 say Not enough RAM to boot slitaz. Trying hacker mode...
1227 default hacker
1228 label hacker
1229 KERNEL /boot/bzImage
1230 append rw root=/dev/null vga=normal
1232 label reboot
1233 EOT
1235 if [ -s $1/c32box.c32 ]; then
1236 cat >> $1/noram.cfg <<EOT
1237 COM32 c32box.c32
1238 append reboot
1240 label poweroff
1241 COM32 c32box.c32
1242 append poweroff
1244 EOT
1245 else
1246 echo " com32 reboot.c32" >> $1/noram.cfg
1247 fi
1249 # Restore real label names
1250 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1251 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1252 while read pat; do
1253 sed -i "s/slitaz$pat/" $files
1254 done
1255 status
1259 # Uncompress rootfs or module to stdout
1261 uncompress() {
1262 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1263 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1267 # Install a missing package
1269 install_package() {
1270 if [ -z "$2" ]; then
1271 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1272 else
1273 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1274 fi
1275 case "$answer" in
1276 y)
1277 # We don't want package on host cache.
1278 action 'Getting and installing package: %s' "$1"
1279 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1280 status ;;
1281 *)
1282 return 1 ;;
1283 esac
1287 # Check iso for loram transformation
1289 check_iso_for_loram() {
1290 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1291 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1295 # Remove duplicated files in $1/efi/boot from $1/boot
1297 cleanup_efi_boot() {
1298 [ -s $1/boot/isolinux/efi.img ] &&
1299 [ ! -x $1/boot/isolinux/efi.img ] &&
1300 rm -f $1/boot/isolinux/efi.img
1301 for i in $1/efi/boot/* ; do
1302 [ -f $i ] || continue
1303 case "$i" in
1304 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1305 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1306 rm $1/efi/boot/linux.cmdline ;;
1307 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1308 rm $1/efi/boot/linux.cmdline* ;;
1309 esac
1310 rm -f $i
1311 rmdir $1/efi/boot && rmdir $1/efi
1312 done 2> /dev/null
1316 # Build initial rootfs for loram ISO ram/cdrom/http
1318 build_initfs() {
1319 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1320 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1321 mirror3.slitaz.org mirror.slitaz.org"
1322 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1323 [ -z "$version" ] && die "Can't find the kernel version." \
1324 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1326 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1327 need_lib=false
1328 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1329 mkdir -p $TMP_DIR/initfs/$i
1330 done
1331 ln -s bin $TMP_DIR/initfs/sbin
1332 ln -s . $TMP_DIR/initfs/usr
1333 for aufs in aufs overlayfs; do
1334 for v in $version ; do
1335 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1336 install_package ${v/*taz/linux}-$aufs $v && continue
1337 done
1338 install_package $aufs $version && break
1339 done || return 1
1340 [ -s /init ] || install_package slitaz-boot-scripts
1341 cp /init $TMP_DIR/initfs/
1342 for v in $version ; do
1343 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1344 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1345 done
1346 if [ "$1" = 'cdrom' ]; then
1347 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1348 else
1349 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1350 for v in $version ; do
1351 while [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; do
1352 install_package linux-squashfs $v || return 1
1353 done
1354 done
1355 for v in $version ; do
1356 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1357 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1358 done
1359 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1360 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1361 fi
1362 if [ "$1" = 'http' ]; then
1363 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1364 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1365 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1366 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1367 cp -a /dev/fuse $TMP_DIR/initfs/dev
1368 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1369 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1370 else
1371 need_lib=true
1372 fi
1373 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1374 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1375 else
1376 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1377 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1378 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1379 cp -a /lib/librt* $TMP_DIR/initfs/lib
1380 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1381 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1382 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1383 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1384 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1385 need_lib=true
1386 fi
1387 cd $TMP_DIR/fs
1388 echo 'Getting slitaz-release & ethernet modules...'
1389 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1390 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1391 [ -s rootfs* ] || continue
1392 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1393 rm -f rootfs*
1394 done 2>&1 > /dev/null
1395 cd - > /dev/null
1396 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1397 for v in $version ; do
1398 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1399 -type f -name '*.ko*' | while read mod; do
1400 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1401 uncompress $mod > $f
1402 grep -q alias=pci: $f || rm -f $f
1403 done
1404 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1405 f=$(basename $i)..z
1406 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1407 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1408 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1409 for j in $deps; do
1410 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1411 uncompress $mod > $(echo $j | sed s/..z$//)
1412 done
1413 done
1414 done
1415 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"
1416 _n 'List of URLs to insert: '
1417 read -t 30 urliso2
1418 urliso="$urliso2 $urliso"
1419 fi
1420 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1421 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1422 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1423 else
1424 cp /bin/busybox $TMP_DIR/initfs/bin
1425 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1426 cp /sbin/insmod $TMP_DIR/initfs/bin
1427 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1428 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1429 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1430 fi
1431 need_lib=true
1432 fi
1433 bins="sh switch_root"
1434 [ "$(echo ls | chroot $TMP_DIR/initfs busybox sh 2> /dev/null)" ] ||
1435 bins="$($TMP_DIR/initfs/bin/busybox | awk \
1436 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g')"
1437 for i in $bins ; do
1438 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1439 done
1440 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1441 for v in $version ; do
1442 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1443 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1444 done
1445 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1446 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1447 cp -a $i $TMP_DIR/initfs/dev
1448 done
1449 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1450 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1451 cp -a $i $TMP_DIR/initfs/dev
1452 done 2>/dev/null
1453 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1454 cp -a $i $TMP_DIR/initfs/lib
1455 done
1456 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1457 #!/bin/sh
1459 getarg() {
1460 grep -q " \$1=" /proc/cmdline || return 1
1461 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1462 return 0
1465 copy_rootfs() {
1466 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1467 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1468 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1469 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1470 path=/mnt/
1471 return 0
1472 else
1473 rm -f /mnt/rootfs*
1474 return 1
1475 fi
1478 echo "Switching / to tmpfs..."
1479 mount -t proc proc /proc
1480 size="\$(grep rootfssize= < /proc/cmdline | \\
1481 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1482 [ -n "\$size" ] || size="-o size=90%"
1484 mount -t sysfs sysfs /sys
1485 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1486 [ -s \$i ] && continue
1487 echo -en "Probe \$i \\r"
1488 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1489 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1490 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1491 insmod /lib/modules/\$k.ko 2> /dev/null
1492 done
1493 echo "Loading \$i"
1494 insmod \$i 2> /dev/null
1495 break
1496 done
1497 done
1498 umount /sys
1499 while read var default; do
1500 eval \$var=\$default
1501 getarg \$var \$var
1502 done <<EOT
1503 eth eth0
1504 dns 208.67.222.222,208.67.220.220
1505 netmask 255.255.255.0
1506 gw
1507 ip
1508 EOT
1509 grep -q \$eth /proc/net/dev || sh
1510 if [ -n "\$ip" ]; then
1511 ifconfig \$eth \$ip netmask \$netmask up
1512 route add default gateway \$gw
1513 for i in \$(echo \$dns | sed 's/,/ /g'); do
1514 echo "nameserver \$i" >> /etc/resolv.conf
1515 done
1516 else
1517 udhcpc -f -q -s /lib/udhcpc -i \$eth
1518 fi
1519 for i in $urliso ; do
1520 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1521 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"
1522 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1523 done
1524 getarg urliso URLISO
1525 DIR=fs
1526 if getarg loram DIR; then
1527 DEVICE=\${DIR%,*}
1528 DIR=/\${DIR#*,}
1529 fi
1530 mount -t tmpfs \$size tmpfs /mnt
1531 path2=/mnt/.httpfs/
1532 path=/mnt/.cdrom/
1533 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1534 while [ ! -d \$path/boot ]; do
1535 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1536 httpfs \$i \$path2 && echo \$i && break
1537 done
1538 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1539 done
1541 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1542 umount /proc
1543 branch=:/mnt/.cdrom/\$DIR
1544 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1545 branch=
1546 lp=1
1547 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1548 [ -s \$i ] && insmod \$i
1549 done 2> /dev/null
1550 for i in \${path}boot/rootfs?.* ; do
1551 fs=\${i#*root}
1552 branch=\$branch:/mnt/.\$fs
1553 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1554 losetup -o 124 /dev/loop\$lp \$i
1555 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1556 lp=\$((\$lp+1))
1557 done
1558 fi
1559 mkdir -p /mnt/.rw/mnt/.httpfs
1560 while read type opt; do
1561 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1562 [ -s \$i ] && insmod \$i &&
1563 mount -t \$type -o \$opt none /mnt && break 2
1564 done
1565 done <<EOT
1566 aufs br=/mnt/.rw\$branch
1567 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1568 EOT
1569 rm -rf /lib/modules
1570 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1571 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1572 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1573 EOTEOT
1574 chmod +x $TMP_DIR/initfs/init
1575 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1576 [ -s $i ] || continue
1577 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1578 rm -f $i
1579 done 2>/dev/null
1580 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1581 lzma e $TMP_DIR/initfs.gz -si
1582 lzma_set_size $TMP_DIR/initfs.gz
1583 rm -rf $TMP_DIR/initfs
1584 align_to_32bits $TMP_DIR/initfs.gz
1585 return 0
1589 # Move each initramfs to squashfs
1591 build_loram_rootfs() {
1592 rootfs_sizes=""
1593 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1594 mkdir -p $TMP_DIR/fs
1595 cd $TMP_DIR/fs
1596 uncompress $i | cpio -idm
1597 deduplicate
1598 cd - > /dev/null
1599 rootfs=$TMP_DIR/$(basename $i 64)
1600 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1601 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1602 cd $TMP_DIR
1603 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1604 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1605 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1606 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1607 rm -f $rootfs
1608 mv ${rootfs%64}.cpio $rootfs
1609 cd - > /dev/null
1610 rm -rf $TMP_DIR/fs
1611 done
1615 # Move meta boot configuration files to basic configuration files
1616 # because meta loram flavor is useless when rootfs is not loaded in RAM
1618 unmeta_boot() {
1619 local root=${1:-$TMP_DIR/loramiso}
1620 if [ -f $root/boot/isolinux/noram.cfg ]; then
1621 # We keep enough information to do unloram...
1622 [ -s $root/boot/isolinux/common.cfg ] &&
1623 sed -i 's/label slitaz/label orgslitaz/' \
1624 $root/boot/isolinux/common.cfg
1625 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1626 shift
1627 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1628 $root/boot/isolinux/isolinux.cfg
1629 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1630 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1631 $root/boot/isolinux/*.cfg
1632 fi
1636 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1637 # These squashfs may be loaded in RAM at boot time.
1638 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1639 # Meta flavors are converted to normal flavors.
1641 build_loram_cdrom() {
1642 build_initfs cdrom || return 1
1643 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1644 cleanup_efi_boot $TMP_DIR/loramiso
1645 mkdir $TMP_DIR/loramiso/fs
1646 cd $TMP_DIR/loramiso/fs
1647 for i in $( ls ../boot/root* | sort -r ) ; do
1648 uncompress $i | cpio -idmu
1649 rm -f $i
1650 done
1651 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1652 cd - >/dev/null
1653 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1654 unmeta_boot
1655 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1656 busybox sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1657 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1658 busybox sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' \
1659 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1660 create_iso $OUTPUT $TMP_DIR/loramiso
1664 # Create http bootstrap to load and remove loram_cdrom
1665 # Meta flavors are converted to normal flavors.
1667 build_loram_http() {
1668 build_initfs http || return 1
1669 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1670 cleanup_efi_boot $TMP_DIR/loramiso
1671 rm -f $TMP_DIR/loramiso/boot/rootfs*
1672 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1673 unmeta_boot
1674 create_iso $OUTPUT $TMP_DIR/loramiso
1678 # Update meta flavor selection sizes.
1679 # Reduce sizes with rootfs gains.
1681 update_metaiso_sizes() {
1682 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1683 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1684 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1685 do
1686 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1687 local sizes="$rootfs_sizes"
1688 local new
1689 set -- $append
1690 shift
1691 [ "$1" = "ifmem" ] && shift
1692 new=""
1693 while [ -n "$2" ]; do
1694 local s
1695 case "$1" in
1696 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1697 *M) s=$(( ${1%M} * 1024 ));;
1698 *) s=${1%K};;
1699 esac
1700 sizes=${sizes#* }
1701 for i in $sizes ; do
1702 s=$(( $s - $i ))
1703 done
1704 new="$new $s $2"
1705 shift 2
1706 done
1707 busybox sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1708 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1709 busybox sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1710 busybox sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1711 busybox sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|autologin|screen=text &|;s|,[^ ]*||}' $cfg
1712 done
1716 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1717 # Meta flavor selection sizes are updated.
1719 build_loram_ram() {
1720 build_initfs ram || return 1
1721 build_loram_rootfs "$1"
1722 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1723 cleanup_efi_boot $TMP_DIR/loramiso
1724 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1725 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1726 update_metaiso_sizes
1727 create_iso $OUTPUT $TMP_DIR/loramiso
1731 # Remove files installed by packages
1733 find_flavor_rootfs() {
1734 for i in $1/etc/tazlito/*.extract; do
1735 [ -e $i ] || continue
1736 chroot $1 /bin/sh ${i#$1}
1737 done
1739 # Clean hardlinks and files patched by genisofs in /boot
1740 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1741 rm -f $1/boot/$i*
1742 done
1744 # Clean files generated in post_install
1745 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1746 $1/dev/core $1/dev/fd $1/dev/std*
1748 # Verify md5
1749 cat $1$INSTALLED/*/md5sum | \
1750 while read md5 file; do
1751 [ -e "$1$file" ] || continue
1752 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1753 rm -f "$1$file"
1754 done
1756 # Check configuration files
1757 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1758 [ -e $i ] || continue
1759 mkdir /tmp/volatile$$
1760 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1761 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1762 while read file ; do
1763 [ -e "$1/$file" ] || continue
1764 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1765 done
1766 rm -rf /tmp/volatile$$
1767 done
1769 # Remove other files blindly
1770 for i in $1$INSTALLED/*/files.list; do
1771 while read file; do
1772 [ "$1$file" -nt "$i" ] && continue
1773 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1774 [ -d "$1$file" ] || rm -f "$1$file"
1775 done < $i
1776 done
1778 # Remove tazpkg files and tmp files
1779 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1780 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1781 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1782 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1783 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1785 # Cleanup directory tree
1786 cd $1
1787 find * -type d | sort -r | while read dir; do
1788 rmdir "$dir" 2>/dev/null
1789 done
1790 cd - > /dev/null
1794 # Get byte(s) from a binary file
1796 get() {
1797 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1801 # Get cpio flavor info from the ISO image
1803 flavordata() {
1804 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1805 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1809 # Restore undigest mirrors
1811 restore_mirrors() {
1812 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1813 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1815 action 'Restoring mirrors...'
1816 if [ -d "$undigest.bak" ]; then
1817 [ -d "$undigest" ] && rm -r "$undigest"
1818 mv "$undigest.bak" "$undigest"
1819 fi
1820 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1821 :; status
1825 # Setup undigest mirrors
1827 setup_mirrors() {
1828 # Setup mirrors in plain system or in chroot (with variable root=)
1829 local mirrorlist="$1" fresh repacked
1830 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1832 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1833 restore_mirrors
1835 _ 'Setting up mirrors for %s...' "$root/"
1836 # Backing up current undigest mirrors and priority
1837 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1838 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1839 rm -rf '/var/www/tazlito/'
1840 mkdir -p '/var/www/tazlito/'
1842 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1843 fresh='/home/slitaz/packages'
1844 if [ -d "$fresh" ]; then
1845 # Setup first undigest mirror
1846 mkdir -p "$undigest/fresh"
1847 echo "$fresh" > "$undigest/fresh/mirror"
1848 echo 'fresh' >> "$priority"
1849 # Rebuild mirror DB if needed
1850 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1851 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1852 tazpkg mkdb "$fresh" --forced --root=''
1853 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1854 fi
1856 # Repacked packages: high priority
1857 repacked="$PACKAGES_REPOSITORY"
1858 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1859 # According to Tazlito setup file (tazlito.conf):
1860 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1861 # or
1862 # WORK_DIR="/home/slitaz"
1863 # and
1864 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1865 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1867 # Setup second undigest mirror
1868 mkdir -p "$undigest/repacked"
1869 echo "$repacked" > "$undigest/repacked/mirror"
1870 echo 'repacked' >> "$priority"
1871 # Rebuild mirror DB if needed
1872 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1873 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1874 tazpkg mkdb "$repacked" --forced --root=''
1875 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1876 fi
1878 # All repositories listed in mirrors list: normal priority
1879 [ -e "$mirrorlist" ] && \
1880 while read mirror; do
1881 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1882 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1883 mkdir -p "$undigest/$mirrorid"
1884 echo "$mirror" > "$undigest/$mirrorid/mirror"
1885 echo "$mirrorid" >> "$priority"
1886 done < "$mirrorlist"
1888 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1890 # Show list of mirrors
1891 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1892 function show(num, name, url) {
1893 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1896 num++;
1897 "cat " db "/undigest/" $0 "/mirror" | getline url;
1898 show(num, $0, url);
1900 END {
1901 num++;
1902 "cat " db "/mirror" | getline url;
1903 show(num, "main", url);
1904 }' "$priority"
1906 tazpkg recharge --quiet >/dev/null
1910 # Get list of 'packages.info' lists using priority
1912 pi_lists() {
1913 local pi
1914 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1915 local priority="$root$LOCALSTATE/priority"
1916 local undigest="$root$LOCALSTATE/undigest"
1919 [ -s "$priority" ] && cat "$priority"
1920 echo 'main'
1921 [ -d "$undigest" ] && ls "$undigest"
1922 } | awk -vun="$undigest/" '
1924 if (arr[$0] != 1) {
1925 arr[$0] = 1;
1926 print un $0 "/packages.info";
1928 }' | sed 's|/undigest/main||' | \
1929 while read pi; do
1930 [ -e "$pi" ] && echo "$pi"
1931 done
1935 # Strip versions from packages list
1937 strip_versions() {
1938 if [ -n "$stripped" ]; then
1939 action 'Consider list %s already stripped' "$(basename "$1")"
1940 status
1941 return 0
1942 fi
1943 action 'Strip versions from list %s...' "$(basename "$1")"
1944 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1945 [ -f "$in_list" ] || die "List '$in_list' not found."
1947 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1948 awk '
1950 if (FILENAME ~ "packages.info") {
1951 # Collect package names
1952 FS = "\t"; pkg[$1] = 1;
1953 } else {
1954 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1955 while (NF > 1 && ! pkg[$0])
1956 NF --;
1957 printf "%s\n", $0;
1959 }' $(pi_lists) "$in_list" > "$tmp_list"
1961 cat "$tmp_list" > "$in_list"
1962 rm "$tmp_list"
1963 status
1967 # Display list of unknown packages (informative)
1969 display_unknown() {
1970 [ -s "$1" ] || return
1971 echo "Unknown packages:" >&2
1972 cat "$1" >&2
1973 rm "$1"
1977 # Display warnings about critical packages absent (informative)
1979 display_warn() {
1980 [ -s "$1" ] || return
1981 echo "Absent critical packages:" >&2
1982 cat "$1" >&2
1983 rm "$1"
1984 echo "Probably ISO image will be unusable."
1988 # Install packages to rootfs
1990 install_list_to_rootfs() {
1991 local list="$1" rootfs="$2" pkg i ii
1992 local undigest="$rootfs/var/lib/tazpkg/undigest"
1994 # initial tazpkg setup in empty rootfs
1995 tazpkg --root=$rootfs >/dev/null 2>&1
1996 # pass current 'mirror' to the rootfs
1997 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1998 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1999 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
2000 # link rootfs packages cache to the regular packages cache
2001 rm -r "$rootfs/var/cache/tazpkg"
2002 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
2004 setup_mirrors mirrors
2006 # Just in case if flavor doesn't contain "tazlito" package
2007 mkdir -p "$rootfs/etc/tazlito"
2009 newline
2011 # Choose detailed log with --detailed
2012 if [ -n "$detailed" ]; then
2013 while read pkg; do
2014 separator '-'
2015 echo $pkg
2016 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2017 done < $list
2018 separator '='
2019 else
2020 while read pkg; do
2021 action 'Installing package: %s' "$pkg"
2022 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2023 status
2024 done < $list
2025 fi
2026 newline
2028 restore_mirrors
2029 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2030 for i in fresh repacked; do
2031 ii="$undigest/$i"
2032 [ -d "$ii" ] && rm -rf "$ii"
2033 ii="$rootfs/var/lib/tazpkg/priority"
2034 if [ -f "$ii" ]; then
2035 sed -i "/$i/d" "$ii"
2036 [ -s "$ii" ] || rm "$ii"
2037 fi
2038 done
2039 [ -d "$undigest" ] && \
2040 for i in $(find "$undigest" -type f); do
2041 # Remove all undigest PKGDB files but 'mirror'
2042 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2043 done
2044 [ -d "$undigest" ] && \
2045 rmdir --ignore-fail-on-non-empty "$undigest"
2047 # Un-link packages cache
2048 rm "$rootfs/var/cache/tazpkg"
2050 # Clean /var/lib/tazpkg
2051 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2057 ####################
2058 # Tazlito commands #
2059 ####################
2061 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2062 case "$0" in
2063 *reduplicate)
2064 find ${@:-.} ! -type d -links +1 \
2065 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2066 exit 0 ;;
2067 *deduplicate)
2068 deduplicate "$@"
2069 exit 0 ;;
2070 esac
2073 case "$COMMAND" in
2074 stats)
2075 # Tazlito general statistics from the config file.
2077 title 'Tazlito statistics'
2078 optlist "\
2079 Config file : $CONFIG_FILE
2080 ISO name : $ISO_NAME.iso
2081 Volume name : $VOLUM_NAME
2082 Prepared : $PREPARED
2083 Packages repository : $PACKAGES_REPOSITORY
2084 Distro directory : $DISTRO
2085 Additional files : $ADDFILES
2086 " | sed '/: $/d'
2087 footer
2088 ;;
2091 list-addfiles)
2092 # Simple list of additional files in the rootfs
2093 newline
2094 if [ -d "$ADDFILES/rootfs" ]; then
2095 cd $ADDFILES
2096 find rootfs -type f
2097 else
2098 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2099 fi
2100 newline
2101 ;;
2104 gen-config)
2105 # Generate a new config file in the current dir or the specified
2106 # directory by $2.
2108 if [ -n "$2" ]; then
2109 mkdir -p "$2" && cd "$2"
2110 fi
2112 newline
2113 action 'Generating empty tazlito.conf...'
2114 empty_config_file
2115 status
2117 separator
2118 if [ -f 'tazlito.conf' ] ; then
2119 _ 'Configuration file is ready to edit.'
2120 _ 'File location: %s' "$(pwd)/tazlito.conf"
2121 newline
2122 fi
2123 ;;
2126 configure)
2127 # Configure a tazlito.conf config file. Start by getting
2128 # a empty config file and sed it.
2130 if [ -f 'tazlito.conf' ]; then
2131 rm tazlito.conf
2132 else
2133 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2134 'or in the same directory of the file you want to configure.'
2135 cd /etc
2136 fi
2138 empty_config_file
2140 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2142 # ISO name.
2143 echo -n "ISO name : " ; read answer
2144 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2145 # Volume name.
2146 echo -n "Volume name : " ; read answer
2147 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2148 # Packages repository.
2149 echo -n "Packages repository : " ; read answer
2150 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2151 # Distro path.
2152 echo -n "Distro path : " ; read answer
2153 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2154 footer "Config file is ready to use."
2155 echo 'You can now extract an ISO or generate a distro.'
2156 newline
2157 ;;
2160 gen-iso)
2161 # Simply generate a new iso.
2163 check_root
2164 verify_rootcd
2165 gen_livecd_isolinux
2166 distro_stats
2167 ;;
2170 gen-initiso)
2171 # Simply generate a new initramfs with a new iso.
2173 check_root
2174 verify_rootcd
2175 gen_initramfs "$ROOTFS"
2176 gen_livecd_isolinux
2177 distro_stats
2178 ;;
2181 extract-distro|extract-iso)
2182 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2184 check_root
2185 ISO_IMAGE="$2"
2186 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2187 'Example:\n tazlito image.iso /path/target'
2189 # Set the distro path by checking for $3 on cmdline.
2190 TARGET="${3:-$DISTRO}"
2192 # Exit if existing distro is found.
2193 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2194 'Please clean the distro tree or change directory path.'
2196 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2198 # Start to mount the ISO.
2199 action 'Mounting ISO image...'
2200 mkdir -p "$TMP_DIR"
2201 # Get ISO file size.
2202 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2203 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2204 sleep 2
2205 # Prepare target dir, copy the kernel and the rootfs.
2206 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2207 status
2209 action 'Copying the Linux kernel...'
2210 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2211 make_bzImage_hardlink "$TARGET/rootcd/boot"
2212 else
2213 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2214 fi
2215 status
2217 for i in $(ls $TMP_DIR); do
2218 [ "$i" = 'boot' ] && continue
2219 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2220 done
2222 for loader in isolinux syslinux extlinux grub; do
2223 [ -d "$TMP_DIR/boot/$loader" ] || continue
2224 action 'Copying %s files...' "$loader"
2225 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2226 status
2227 done
2229 action 'Copying the rootfs...'
2230 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2231 status
2233 cleanup_efi_boot "$TARGET/rootcd"
2235 # Extract initramfs.
2236 cd "$TARGET/rootfs"
2237 action 'Extracting the rootfs...'
2238 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2239 extract_rootfs "$i" "$TARGET/rootfs"
2240 done
2241 # unpack /usr
2242 for i in etc/tazlito/*.extract; do
2243 [ -f "$i" ] && . $i ../rootcd
2244 done
2245 # Umount and remove temp directory and cd to $TARGET to get stats.
2246 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2247 cd ..
2248 status
2250 newline
2251 separator
2252 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2253 echo "Distro tree : $(pwd)"
2254 echo "Rootfs size : $(du -sh rootfs)"
2255 echo "Rootcd size : $(du -sh rootcd)"
2256 footer
2257 ;;
2260 list-flavors)
2261 # Show available flavors.
2262 list='/etc/tazlito/flavors.list'
2263 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2264 title 'List of flavors'
2265 cat $list
2266 footer
2267 ;;
2270 show-flavor)
2271 # Show flavor descriptions.
2272 set -e
2273 flavor=${2%.flavor}
2274 flv_dir="$(extract_flavor "$flavor")"
2275 desc="$flv_dir/$flavor.desc"
2276 if [ -n "$brief" ]; then
2277 if [ -z "$noheader" ]; then
2278 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2279 separator
2280 fi
2281 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2282 "$(field ISO "$desc")" \
2283 "$(field Rootfs "$desc")" \
2284 "$(field Description "$desc")"
2285 else
2286 separator
2287 cat "$desc"
2288 fi
2289 cleanup
2290 ;;
2293 gen-liveflavor)
2294 # Generate a new flavor from the live system.
2295 FLAVOR=${2%.flavor}
2296 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2298 case "$FLAVOR" in
2299 -?|-h*|--help)
2300 cat <<EOT
2301 SliTaz Live Tool - Version: $VERSION
2303 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2305 $(boldify '<flavor-patch-file> format:')
2306 $(optlist "\
2307 code data
2308 + package to add
2309 - package to remove
2310 ! non-free package to add
2311 ? display message
2312 @ flavor description
2313 ")
2315 $(boldify 'Example:')
2316 $(optlist "\
2317 @ Developer tools for SliTaz maintainers
2318 + slitaz-toolchain
2319 + mercurial
2320 ")
2321 EOT
2322 exit 1
2323 ;;
2324 esac
2325 mv /etc/tazlito/distro-packages.list \
2326 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2327 rm -f distro-packages.list non-free.list 2>/dev/null
2328 tazpkg recharge
2330 DESC=""
2331 [ -n "$3" ] && \
2332 while read action pkg; do
2333 case "$action" in
2334 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2335 -) yes | tazpkg remove $pkg ;;
2336 !) echo $pkg >> non-free.list ;;
2337 @) DESC="$pkg" ;;
2338 \?) echo -en "$pkg"; read action ;;
2339 esac
2340 done < $3
2342 yes '' | tazlito gen-distro
2343 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2344 mv /etc/tazlito/distro-packages.list.$$ \
2345 /etc/tazlito/distro-packages.list 2>/dev/null
2346 ;;
2349 gen-flavor)
2350 # Generate a new flavor from the last ISO image generated
2351 FLAVOR=${2%.flavor}
2352 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2354 title 'Flavor generation'
2355 check_rootfs
2356 FILES="$FLAVOR.pkglist"
2358 action 'Creating file %s...' "$FLAVOR.flavor"
2359 for i in rootcd rootfs; do
2360 if [ -d "$ADDFILES/$i" ] ; then
2361 FILES="$FILES\n$FLAVOR.$i"
2362 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2363 fi
2364 done
2365 status
2367 answer=$(grep -s ^Description $FLAVOR.desc)
2368 answer=${answer#Description : }
2369 if [ -z "$answer" ]; then
2370 echo -n "Description: "
2371 read answer
2372 fi
2374 action 'Compressing flavor %s...' "$FLAVOR"
2375 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2376 echo "Description : $answer" >> $FLAVOR.desc
2377 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2378 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2379 for i in $(ls $ROOTFS$INSTALLED); do
2380 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2381 EXTRAVERSION=""
2382 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2383 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2384 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2385 echo "$i" >> $FLAVOR.nonfree
2386 else
2387 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2388 fi
2389 done
2390 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2391 for i in $LOCALSTATE/undigest/*/mirror ; do
2392 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2393 done
2394 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2395 touch -t 197001010100.00 $FLAVOR.*
2396 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2397 rm $(echo -e $FILES)
2398 status
2400 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2401 ;;
2404 upgrade-flavor)
2405 # Strip versions from pkglist and update estimated numbers in flavor.desc
2406 flavor="${2%.flavor}"
2407 set -e
2408 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2409 set +e
2411 flv_dir="$(extract_flavor "$flavor")"
2413 strip_versions "$flv_dir/$flavor.pkglist"
2415 action 'Updating %s...' "$flavor.desc"
2417 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2418 set -- $(module calc_sizes "$flv_dir" "$flavor")
2419 restore_mirrors >/dev/null
2421 sed -i -e '/Image is ready/d' \
2422 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2423 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2424 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2425 -e "s|\(Packages *:\).*$|\1 $4|" \
2426 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2427 "$flv_dir/$flavor.desc"
2429 pack_flavor "$flv_dir" "$flavor"
2430 status
2431 display_unknown "$flv_dir/err"
2432 display_warn "$flv_dir/warn"
2433 cleanup
2434 ;;
2437 extract-flavor)
2438 # Extract a flavor into $FLAVORS_REPOSITORY
2439 flavor="${2%.flavor}"
2440 set -e
2441 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2442 set +e
2444 action 'Extracting %s...' "$flavor.flavor"
2445 flv_dir="$(extract_flavor "$flavor" full)"
2446 storage="$FLAVORS_REPOSITORY/$flavor"
2448 rm -rf "$storage" 2>/dev/null
2449 mkdir -p "$storage"
2450 cp -a "$flv_dir"/* "$storage"
2451 rm "$storage/description"
2452 status
2454 strip_versions "$storage/packages.list"
2456 cleanup
2457 ;;
2460 pack-flavor)
2461 # Create a flavor from $FLAVORS_REPOSITORY.
2462 flavor=${2%.flavor}
2463 storage="$FLAVORS_REPOSITORY/$flavor"
2465 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2467 action 'Creating flavor %s...' "$flavor"
2468 tmp_dir="$(mktemp -d)"
2470 while read from to; do
2471 [ -s "$storage/$from" ] || continue
2472 cp -a "$storage/$from" "$tmp_dir/$to"
2473 done <<EOT
2474 mirrors $flavor.mirrors
2475 distro.sh $flavor-distro.sh
2476 receipt $flavor.receipt
2477 non-free.list $flavor.nonfree
2478 EOT
2480 # Build the package list.
2481 # It can include a list from another flavor with the keyword @include
2482 if [ -s "$storage/packages.list" ]; then
2483 include=$(grep '^@include' "$storage/packages.list")
2484 if [ -n "$include" ]; then
2485 include=${include#@include }
2486 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2487 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2488 else
2489 echo -e "\nERROR: Can't find include package list from $include\n"
2490 fi
2491 fi
2492 # Generate the final/initial package list
2493 [ -s "$storage/packages.list" ] && \
2494 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2495 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2496 fi
2498 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2499 # Process multi-rootfs flavor
2500 . "$storage/receipt"
2501 set -- $ROOTFS_SELECTION
2502 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2503 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2504 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2506 for i in rootcd rootfs; do
2507 mkdir "$tmp_dir/$i"
2508 # Copy extra files from the first flavor
2509 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2510 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2511 # Overload extra files by meta flavor
2512 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2513 [ -n "$(ls $tmp_dir/$i)" ] &&
2514 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2515 dogzip "$tmp_dir/$flavor.$i"
2516 rm -rf "$tmp_dir/$i"
2517 done
2518 else
2519 # Process plain flavor
2520 for i in rootcd rootfs; do
2521 [ -d "$storage/$i" ] || continue
2522 (cd "$storage/$i";
2523 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2524 done
2525 fi
2527 unset VERSION MAINTAINER ROOTFS_SELECTION
2528 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2529 ROOTFS_SIZE="$1 (estimated)"
2530 INITRAMFS_SIZE="$2 (estimated)"
2531 ISO_SIZE="$3 (estimated)"
2532 PKGNUM="$4"
2533 . "$storage/receipt"
2535 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2536 Flavor : $FLAVOR
2537 Description : $SHORT_DESC
2538 Version : $VERSION
2539 Maintainer : $MAINTAINER
2540 LiveCD RAM size : $FRUGAL_RAM
2541 Rootfs list : $ROOTFS_SELECTION
2542 Build date : $(date '+%Y%m%d at %T')
2543 Packages : $PKGNUM
2544 Rootfs size : $ROOTFS_SIZE
2545 Initramfs size : $INITRAMFS_SIZE
2546 ISO image size : $ISO_SIZE
2547 ================================================================================
2549 EOT
2551 rm -f $tmp_dir/packages.list
2552 pack_flavor "$tmp_dir" "$flavor"
2553 status
2554 display_unknown "$tmp_dir/err"
2555 display_warn "$flv_dir/warn"
2556 cleanup
2557 ;;
2560 get-flavor)
2561 # Get a flavor's files and prepare for gen-distro.
2562 flavor=${2%.flavor}
2563 title 'Preparing %s distro flavor' "$flavor"
2564 set -e
2565 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2566 set +e
2568 action 'Cleaning %s...' "$DISTRO"
2569 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2570 # Clean old files
2571 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2572 [ -f "$i" ] && rm "$i"
2573 done
2574 mkdir -p "$DISTRO"
2575 status
2577 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2579 action 'Extracting flavor %s...' "$flavor.flavor"
2580 flv_dir="$(extract_flavor "$flavor" info)"
2581 cp -a "$flv_dir"/* .
2582 mv packages.list distro-packages.list
2583 mv -f info /etc/tazlito
2584 status
2586 for i in rootcd rootfs; do
2587 if [ -d "$i" ]; then
2588 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2589 fi
2590 done
2592 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2593 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2595 action 'Updating %s...' 'tazlito.conf'
2596 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2597 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2598 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2599 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2600 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2601 status
2603 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2604 cleanup
2605 ;;
2608 iso2flavor)
2609 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2610 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2612 FLAVOR=${3%.flavor}
2613 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2614 mount -o loop,ro $2 $TMP_DIR/iso
2615 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2616 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2617 ! -s $TMP_DIR/flavor/*.desc ]; then
2618 _ 'META flavors are not supported.'
2619 umount -d $TMP_DIR/iso
2620 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2621 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2622 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2623 umount -d $TMP_DIR/iso
2624 else
2625 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2626 uncompress $i | \
2627 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2628 done
2629 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2630 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2631 '/etc/slitaz-release' '/boot/rootfs.gz'
2632 umount -d $TMP_DIR/iso
2633 else
2634 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2635 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2636 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2637 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2638 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2639 umount -d $TMP_DIR/iso
2640 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2641 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2642 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2643 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2644 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2645 < $TMP_DIR/rootfs$INSTALLED.md5
2646 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2647 if [ -s $TMP_DIR/flavor/*desc ]; then
2648 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2649 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2650 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2651 for i in rootfs rootcd ; do
2652 [ -s $TMP_DIR/flavor/*.list$i ] &&
2653 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2654 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2655 done
2656 else
2657 find_flavor_rootfs $TMP_DIR/rootfs
2658 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2659 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2660 for i in rootfs rootcd ; do
2661 [ "$(ls $TMP_DIR/$i)" ] &&
2662 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2663 done
2664 unset VERSION MAINTAINER
2665 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2666 if [ -n "$DESCRIPTION" ]; then
2667 _n 'Flavor version : '; read -t 30 VERSION
2668 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2669 fi
2671 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2672 Flavor : $FLAVOR
2673 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2674 Version : ${VERSION:-1.0}
2675 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2676 LiveCD RAM size : $RAM_SIZE
2677 Build date : $BUILD_DATE
2678 Packages : $PKGCNT
2679 Rootfs size : $ROOTFS_SIZE
2680 Initramfs size : $INITRAMFS_SIZE
2681 ISO image size : $ISO_SIZE
2682 ================================================================================
2684 EOT
2685 longline "Tazlito can't detect each file installed during \
2686 a package post_install. You should extract this flavor (tazlito extract-flavor \
2687 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2688 tree and remove files generated by post_installs.
2689 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2690 repack the flavor (tazlito pack-flavor $FLAVOR)"
2691 fi
2692 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2693 fi
2694 fi
2695 rm -rf $TMP_DIR
2696 ;;
2699 gen-distro)
2700 # Generate a live distro tree with a set of packages.
2702 check_root
2703 start_time=$(date +%s)
2705 # Tazlito options: --iso or --cdrom
2706 CDROM=''
2707 [ -n "$iso" ] && CDROM="-o loop $iso"
2708 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2710 # Check if a package list was specified on cmdline.
2711 if [ -f "$2" ]; then
2712 LIST_NAME="$2"
2713 else
2714 LIST_NAME='distro-packages.list'
2715 fi
2717 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2718 'Please clean the distro tree or change directory path.'
2719 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2720 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2722 # If list not given: build list with all installed packages
2723 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2724 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2725 fi
2727 # Exit if no list name.
2728 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2730 # Start generation.
2731 title 'Tazlito generating a distro'
2733 # Misc checks
2734 mkdir -p "$PACKAGES_REPOSITORY"
2735 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2736 newline
2738 # Mount CD-ROM to be able to repack boot-loader packages
2739 if [ ! -e /boot -a -n "$CDROM" ]; then
2740 mkdir $TMP_MNT
2741 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2742 ln -s "$TMP_MNT/boot" /
2743 if [ ! -d "$ADDFILES/rootcd" ] ; then
2744 mkdir -p "$ADDFILES/rootcd"
2745 for i in $(ls $TMP_MNT); do
2746 [ "$i" = 'boot' ] && continue
2747 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2748 done
2749 fi
2750 else
2751 rmdir "$TMP_MNT"
2752 fi
2753 fi
2755 # Rootfs stuff.
2756 echo 'Preparing the rootfs directory...'
2757 mkdir -p "$ROOTFS"
2758 export root="$ROOTFS"
2759 # pass current 'mirror' to the root
2760 mkdir -p $root/var/lib/tazpkg $root/etc
2761 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2762 cp -f /etc/slitaz-release $root/etc/slitaz-release
2763 strip_versions "$LIST_NAME"
2765 if [ "$REPACK" = 'y' ]; then
2766 # Determine full packages list with all dependencies
2767 tmp_dir="$(mktemp -d)"
2768 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2769 touch "$tmp_dir/full.pkglist"
2770 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2772 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2773 while read pkgname pkgver; do
2774 # Is package in full list?
2775 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2776 # Is package already repacked?
2777 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2778 _ 'Repacking %s...' "$pkgname-$pkgver"
2779 tazpkg repack "$pkgname" --quiet
2780 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2781 status
2782 done
2784 rm -r "$tmp_dir"
2785 fi
2787 if [ -f non-free.list ]; then
2788 # FIXME: working in the ROOTFS chroot?
2789 newline
2790 echo 'Preparing non-free packages...'
2791 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2792 while read pkg ; do
2793 if [ ! -d "$INSTALLED/$pkg" ]; then
2794 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2795 tazpkg get-install get-$pkg
2796 fi
2797 get-$pkg "$ROOTFS"
2798 fi
2799 tazpkg repack $pkg
2800 pkg=$(ls $pkg*.tazpkg)
2801 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2802 mv $pkg $PACKAGES_REPOSITORY
2803 done < non-free.list
2804 fi
2805 cp $LIST_NAME $DISTRO/distro-packages.list
2806 newline
2808 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2810 cd $DISTRO
2811 cp distro-packages.list $ROOTFS/etc/tazlito
2812 # Copy all files from $ADDFILES/rootfs to the rootfs.
2813 if [ -d "$ADDFILES/rootfs" ] ; then
2814 action 'Copying addfiles content to the rootfs...'
2815 cp -a $ADDFILES/rootfs/* $ROOTFS
2816 status
2817 fi
2819 action 'Root filesystem is generated...'; status
2821 # Root CD part.
2822 action 'Preparing the rootcd directory...'
2823 mkdir -p $ROOTCD
2824 status
2826 # Move the boot dir with the Linux kernel from rootfs.
2827 # The efi & boot dirs go directly on the CD.
2828 if [ -d "$ROOTFS/efi" ] ; then
2829 action 'Moving the efi directory...'
2830 mv $ROOTFS/efi $ROOTCD
2831 status
2832 fi
2833 if [ -d "$ROOTFS/boot" ] ; then
2834 action 'Moving the boot directory...'
2835 mv $ROOTFS/boot $ROOTCD
2836 status
2837 fi
2838 cd $DISTRO
2839 # Copy all files from $ADDFILES/rootcd to the rootcd.
2840 if [ -d "$ADDFILES/rootcd" ] ; then
2841 action 'Copying addfiles content to the rootcd...'
2842 cp -a $ADDFILES/rootcd/* $ROOTCD
2843 status
2844 fi
2845 # Execute the distro script used to perform tasks in the rootfs
2846 # before compression. Give rootfs path in arg
2847 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2848 if [ -x "$DISTRO_SCRIPT" ]; then
2849 echo 'Executing distro script...'
2850 sh $DISTRO_SCRIPT $DISTRO
2851 fi
2853 # Execute the custom_rules() found in receipt.
2854 if [ -s "$TOP_DIR/receipt" ]; then
2855 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2856 echo -e "Executing: custom_rules()\n"
2857 . "$TOP_DIR/receipt"
2858 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2859 fi
2860 fi
2862 # Multi-rootfs
2863 if [ -s /etc/tazlito/rootfs.list ]; then
2865 FLAVOR_LIST="$(awk '{
2866 for (i = 2; i <= NF; i+=2)
2867 printf "%s ", $i;
2868 }' /etc/tazlito/rootfs.list)"
2870 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2871 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2872 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2874 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2875 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2876 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2877 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2879 n=0
2880 last=$ROOTFS
2881 while read flavor; do
2882 n=$(($n+1))
2883 mkdir ${ROOTFS}0$n
2884 export root="${ROOTFS}0$n"
2885 # initial tazpkg setup in empty rootfs
2886 tazpkg --root=$root >/dev/null 2>&1
2888 newline
2889 boldify "Building $flavor rootfs..."
2891 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2892 cp "$TOP_DIR/$flavor.flavor" .
2894 if [ ! -s "$flavor.flavor" ]; then
2895 # We may have it in $FLAVORS_REPOSITORY
2896 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2897 tazlito pack-flavor $flavor
2898 else
2899 download $flavor.flavor
2900 fi
2901 fi
2903 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2904 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2905 cp $flavor.pkglist $DISTRO/list-packages0$n
2906 status
2908 strip_versions "$DISTRO/list-packages0$n"
2910 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2912 action 'Updating the boot directory...'
2913 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2914 rm -rf ${ROOTFS}0$n/boot
2916 cd $DISTRO
2917 if [ -s $flavor.rootfs ]; then
2918 _n 'Adding %s rootfs extra files...' "$flavor"
2919 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2920 fi
2922 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2923 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2924 status
2926 rm -f $flavor.flavor install-list
2927 mergefs ${ROOTFS}0$n $last
2928 last=${ROOTFS}0$n
2929 done <<EOT
2930 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2931 EOT
2932 #'
2933 i=$(($n+1))
2934 while [ $n -gt 0 ]; do
2935 mv ${ROOTFS}0$n ${ROOTFS}$i
2936 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2937 gen_initramfs ${ROOTFS}$i
2938 n=$(($n-1))
2939 i=$(($i-1))
2940 export LZMA_HISTORY_BITS=26
2941 done
2942 mv $ROOTFS ${ROOTFS}$i
2943 gen_initramfs ${ROOTFS}$i
2944 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2945 ROOTFS=${ROOTFS}1
2946 else
2947 # Initramfs and ISO image stuff.
2948 gen_initramfs $ROOTFS
2949 fi
2950 gen_livecd_isolinux
2951 distro_stats
2952 cleanup
2953 ;;
2956 clean-distro)
2957 # Remove old distro tree.
2959 check_root
2960 title 'Cleaning: %s' "$DISTRO"
2961 if [ -d "$DISTRO" ] ; then
2962 if [ -d "$ROOTFS" ] ; then
2963 action 'Removing the rootfs...'
2964 rm -f $DISTRO/$INITRAMFS
2965 rm -rf $ROOTFS
2966 status
2967 fi
2968 if [ -d "$ROOTCD" ] ; then
2969 action 'Removing the rootcd...'
2970 rm -rf $ROOTCD
2971 status
2972 fi
2973 action 'Removing eventual ISO image...'
2974 rm -f $DISTRO/$ISO_NAME.iso
2975 rm -f $DISTRO/$ISO_NAME.md5
2976 status
2977 fi
2978 footer
2979 ;;
2982 check-distro)
2983 # Check for a few LiveCD needed files not installed by packages.
2985 # TODO: Remove this function.
2986 # First two files are maintained by tazpkg while it runs on rootfs,
2987 # while last one file should be maintained by tazlito itself.
2988 check_rootfs
2989 title 'Checking distro: %s' "$ROOTFS"
2990 # SliTaz release info.
2991 rel='/etc/slitaz-release'
2992 if [ ! -f "$ROOTFS$rel" ]; then
2993 _ 'Missing release info: %s' "$rel"
2994 else
2995 action 'Release : %s' "$(cat $ROOTFS$rel)"
2996 status
2997 fi
2998 # Tazpkg mirror.
2999 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
3000 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
3001 todomsg
3002 else
3003 action 'Mirror configuration exists...'
3004 status
3005 fi
3006 # Isolinux msg
3007 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
3008 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
3009 todomsg
3010 else
3011 action 'Isolinux message seems good...'
3012 status
3013 fi
3014 footer
3015 ;;
3018 writeiso)
3019 # Writefs to ISO image including /home unlike gen-distro we don't use
3020 # packages to generate a rootfs, we build a compressed rootfs with all
3021 # the current filesystem similar to 'tazusb writefs'.
3023 DISTRO='/home/slitaz/distro'
3024 ROOTCD="$DISTRO/rootcd"
3025 COMPRESSION="${2:-none}"
3026 ISO_NAME="${3:-slitaz}"
3027 check_root
3028 # Start info
3029 title 'Write filesystem to ISO'
3030 longline "The command writeiso will write the current filesystem into a \
3031 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3032 newline
3033 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3035 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3036 # Save some space
3037 rm -rf /var/cache/tazpkg/*
3038 rm -f /var/lib/tazpkg/*.bak
3039 rm -rf $DISTRO
3041 # Optionally remove sound card selection and screen resolution.
3042 if [ -z $LaunchedByTazpanel ]; then
3043 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3044 case $anser in
3045 y)
3046 action 'Removing current sound card and screen configurations...'
3047 rm -f /var/lib/sound-card-driver
3048 rm -f /var/lib/alsa/asound.state
3049 rm -f /etc/X11/xorg.conf ;;
3050 *)
3051 action 'Keeping current sound card and screen configurations...' ;;
3052 esac
3053 status
3054 newline
3056 # Optionally remove i18n settings
3057 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3058 case $anser in
3059 y)
3060 action 'Removing current locale/keymap settings...'
3061 newline > /etc/locale.conf
3062 newline > /etc/keymap.conf ;;
3063 *)
3064 action 'Keeping current locale/keymap settings...' ;;
3065 esac
3066 status
3067 fi
3069 # Clean-up files by default
3070 newline > /etc/udev/rules.d/70-persistent-net.rules
3071 newline > /etc/udev/rules.d/70-persistant-cd.rules
3073 # Create list of files including default user files since it is defined in /etc/passwd
3074 # and some new users might have been added.
3075 cd /
3076 echo 'init' > /tmp/list
3077 for dir in bin etc sbin var dev lib root usr home opt; do
3078 [ -d $dir ] && find $dir
3079 done >> /tmp/list
3081 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3082 [ -d $dir ] && echo $dir
3083 done >> /tmp/list
3085 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3087 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3088 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3089 #fi
3090 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3091 touch /var/log/wtmp
3093 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3094 sed -i "/var\/log\/$removelog/d" /tmp/list
3095 done
3097 # Generate initramfs with specified compression and display rootfs
3098 # size in realtime.
3099 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3101 write_initramfs &
3102 sleep 2
3103 cd - > /dev/null
3104 echo -en "\nFilesystem size:"
3105 while [ ! -f /tmp/rootfs ]; do
3106 sleep 1
3107 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3108 done
3109 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3110 echo -e "\n"
3111 rm -f /tmp/rootfs
3113 # Move freshly generated rootfs to the cdrom.
3114 mkdir -p $ROOTCD/boot
3115 mv -f /$INITRAMFS $ROOTCD/boot
3116 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3118 # Now we need the kernel and isolinux files.
3119 copy_from_cd() {
3120 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3121 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3122 unmeta_boot $ROOTCD
3123 umount /media/cdrom
3126 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3127 copy_from_cd;
3128 elif mount | grep /media/cdrom; then
3129 copy_from_cd;
3130 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3131 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3132 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3133 else
3134 touch /tmp/.write-iso-error
3135 longline "When SliTaz is running in RAM the kernel and bootloader \
3136 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3137 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3138 echo -en "----\nENTER to continue..."; read i
3139 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3140 copy_from_cd
3141 fi
3143 # Generate the iso image.
3144 touch /tmp/.write-iso
3145 newline
3146 cd $DISTRO
3147 create_iso $ISO_NAME.iso $ROOTCD
3148 action 'Creating the ISO md5sum...'
3149 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3150 status
3152 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3153 rm -f /tmp/.write-iso
3155 if [ -z $LaunchedByTazpanel ]; then
3156 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3157 case $anser in
3158 y)
3159 umount /dev/cdrom 2>/dev/null
3160 eject
3161 echo -n "Please insert a blank CD-ROM and press ENTER..."
3162 read i && sleep 2
3163 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3164 echo -en "----\nENTER to continue..."; read i ;;
3165 *)
3166 exit 0 ;;
3167 esac
3168 fi
3169 ;;
3172 burn-iso)
3173 # Guess CD-ROM device, ask user and burn the ISO.
3175 check_root
3176 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3177 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3178 # We can specify an alternative ISO from the cmdline.
3179 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3180 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3182 title 'Tazlito burn ISO'
3183 echo "CD-ROM device : /dev/$DRIVE_NAME"
3184 echo "Drive speed : $DRIVE_SPEED"
3185 echo "ISO image : $iso"
3186 footer
3188 case $(yesorno 'Burn ISO image?' 'n') in
3189 y)
3190 title 'Starting Wodim to burn the ISO...'
3191 sleep 2
3192 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3193 footer 'ISO image is burned to CD-ROM.'
3194 ;;
3195 *)
3196 die 'Exiting. No ISO burned.'
3197 ;;
3198 esac
3199 ;;
3202 merge)
3203 # Merge multiple rootfs into one iso.
3205 if [ -z "$2" ]; then
3206 cat <<EOT
3207 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3209 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3210 i.e: rootfsN is a subset of rootfsN-1
3211 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3212 The boot loader will select the rootfs according to the RAM size detected.
3214 Example:
3215 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3217 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3218 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3220 EOT
3221 exit 2
3222 fi
3224 shift # skip merge
3225 append="$1 slitaz1"
3226 shift # skip size1
3227 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3229 ISO=$1.merged
3231 # Extract filesystems
3232 action 'Mounting %s' "$1"
3233 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3234 status || cleanup_merge
3236 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3237 make_bzImage_hardlink $TMP_DIR/iso/boot
3238 umount -d $TMP_DIR/mnt
3239 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3240 _ '%s is already a merged iso. Aborting.' "$1"
3241 cleanup_merge
3242 fi
3243 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3244 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3245 if [ ! -f /boot/isolinux/ifmem.c32 -a
3246 ! -f /boot/isolinux/c32box.c32 ]; then
3247 cat <<EOT
3248 No file /boot/isolinux/ifmem.c32
3249 Please install syslinux package !
3250 EOT
3251 rm -rf $TMP_DIR
3252 exit 1
3253 fi
3254 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3255 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3256 fi
3258 action 'Extracting %s' 'iso/rootfs.gz'
3259 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3260 [ -d $TMP_DIR/rootfs1/etc ]
3261 status || cleanup_merge
3263 n=1
3264 while [ -n "$2" ]; do
3265 shift # skip rootfs N-1
3266 p=$n
3267 n=$(($n + 1))
3268 append="$append $1 slitaz$n"
3269 shift # skip size N
3270 mkdir -p $TMP_DIR/rootfs$n
3272 action 'Extracting %s' "$1"
3273 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3274 [ -d "$TMP_DIR/rootfs$n/etc" ]
3275 status || cleanup_merge
3277 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3278 action 'Creating %s' "rootfs$p.gz"
3279 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3280 status
3281 done
3282 action 'Creating %s' "rootfs$n.gz"
3283 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3284 status
3285 rm -f $TMP_DIR/iso/boot/rootfs.gz
3286 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3287 create_iso $ISO $TMP_DIR/iso
3288 rm -rf $TMP_DIR
3289 ;;
3292 repack)
3293 # Repack an iso with maximum lzma compression ratio.
3295 ISO=$2
3296 mkdir -p $TMP_DIR/mnt
3298 # Extract filesystems
3299 action 'Mounting %s' "$ISO"
3300 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3301 status || cleanup_merge
3303 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3304 umount -d $TMP_DIR/mnt
3306 for i in $TMP_DIR/iso/boot/rootfs* ; do
3307 action 'Repacking %s' "$(basename $i)"
3308 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3309 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3310 align_to_32bits $i
3311 status
3312 done
3314 create_iso $ISO $TMP_DIR/iso
3315 rm -rf $TMP_DIR
3316 ;;
3319 build-loram)
3320 # Build a Live CD for low RAM systems.
3322 ISO="$2"
3323 OUTPUT="$3"
3324 [ -z "$3" ] && \
3325 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3326 mkdir -p "$TMP_DIR/iso"
3327 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3328 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3329 if ! check_iso_for_loram ; then
3330 umount -d "$TMP_DIR/iso"
3331 die "$ISO is not a valid SliTaz live CD. Abort."
3332 fi
3333 case "$4" in
3334 cdrom) build_loram_cdrom ;;
3335 http) build_loram_http ;;
3336 *) build_loram_ram "$5" ;;
3337 esac
3338 umount $TMP_DIR/iso # no -d: needs /proc
3339 losetup -d $loopdev
3340 rm -rf $TMP_DIR
3341 ;;
3344 emu-iso)
3345 # Emulate an ISO image with Qemu.
3346 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3347 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3348 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3349 echo -e "\nStarting Qemu emulator:\n"
3350 echo -e "qemu $QEMU_OPTS $iso\n"
3351 qemu $QEMU_OPTS $iso
3352 ;;
3355 deduplicate)
3356 # Deduplicate files in a tree
3357 shift
3358 deduplicate "$@"
3359 ;;
3362 usage|*)
3363 # Print usage also for all unknown commands.
3364 usage
3365 ;;
3366 esac
3368 exit 0