tazlito view tazlito @ rev 511

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