tazlito view tazlito @ rev 524

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