tazlito view tazlito @ rev 489

tazlito: fix efi.img md5sum
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Mar 16 20:15:54 2018 +0100 (2018-03-16)
parents 3dee688b1ec1
children 2ca093c3ff30
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-2017 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'
22 # Tazlito configuration variables to be shorter
23 # and to use words rather than numbers.
24 COMMAND="$1"
25 LIST_NAME="$2"
26 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
27 TMP_MNT="/media/tazlito-$$-$RANDOM"
28 TOP_DIR="$(pwd)"
29 INITRAMFS='rootfs.gz'
30 LOCALSTATE='/var/lib/tazpkg'
31 INSTALLED="$LOCALSTATE/installed"
32 CACHE_DIR='/var/cache/tazpkg'
33 MIRROR="$LOCALSTATE/mirror"
34 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
36 log='/var/log/tazlito.log'
37 if [ $(id -u) -eq 0 ]; then
38 newline > $log
39 fi
42 cleanup() {
43 if [ -d "$TMP_MNT" ]; then
44 umount $TMP_MNT
45 rmdir $TMP_MNT
46 rm -f /boot
47 fi
48 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
49 [ -d "$flv_dir" ] && rm -r "$flv_dir"
50 }
53 # Report error and finish work
55 die() {
56 emsg "<n>$(longline "$@")<n> " >&2
57 cleanup
58 exit 1
59 }
62 # Run Tazlito module
63 module() {
64 local mod="$1"; shift
65 /usr/libexec/tazlito/$mod $@
66 }
70 # Try to include config file, continue if command is gen-config or exit.
71 # The main config used by default is in /etc/tazlito.
72 # Specific distro config file can be put in a distro tree.
73 for i in /etc/tazlito "$TOP_DIR"; do
74 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
75 done
77 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
78 die 'Unable to find any configuration file.' \
79 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
81 . $CONFIG_FILE
83 # While Tazpkg is not used the default mirror URL file does not exist
84 # and user can't recharge the list of flavors.
85 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
87 # Set the rootfs and rootcd path with $DISTRO
88 # configuration variable.
89 ROOTFS="$DISTRO/rootfs"
90 ROOTCD="$DISTRO/rootcd"
95 #####################
96 # Tazlito functions #
97 #####################
100 # Print the usage.
102 usage () {
103 [ $(basename $0) == 'tazlito' ] && cat <<EOT
105 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
107 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
109 $(boldify "Commands:")
110 EOT
111 optlist "\
112 usage Print this short usage.
113 stats View Tazlito and distro configuration statistics.
114 list-addfiles Simple list of additional files in the rootfs.
115 gen-config Generate a new configuration file for a distro.
116 configure Configure the main config file or a specific tazlito.conf.
117 gen-iso Generate a new ISO from a distro tree.
118 gen-initiso Generate a new initramfs and ISO from the distro tree.
119 list-flavors List all flavors available on the mirror.
120 gen-flavor Generate a new Live CD description.
121 gen-liveflavor Generate a Live CD description from current system.
122 show-flavor Show Live CD description.
123 get-flavor Get a flavor's list of packages (--noup to skip update).
124 upgrade-flavor Update package list to the latest available versions.
125 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
126 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
127 iso2flavor Create a flavor file from a SliTaz ISO image.
128 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
129 gen-distro Generate a Live distro and ISO from a list of packages.
130 clean-distro Remove all files generated by gen-distro.
131 check-distro Help to check if distro is ready to release.
132 writeiso Use running system to generate a bootable ISO (with /home).
133 merge Merge multiple rootfs into one ISO.
134 deduplicate Deduplicate files in a tree.
135 repack Recompress rootfs into ISO with maximum ratio.
136 build-loram Generate a Live CD for low-RAM systems.
137 emu-iso Emulate an ISO image with QEMU.
138 burn-iso Burn ISO image to a CD-ROM using Wodim.
139 "
140 }
143 yesorno() {
144 local answer
145 echo -n "$1 (y=yes, n=no) [$2] " >&2
146 case "$DEFAULT_ANSWER" in
147 Y|y) answer="y";;
148 N|n) answer="n";;
149 *)
150 read -t 30 answer
151 [ -z "$answer" ] && answer="$2"
152 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
153 ;;
154 esac
155 echo "$answer"
156 }
159 field() {
160 grep "^$1" "$2" | \
161 case "$1" in
162 Desc*) sed 's|^.*: *||';;
163 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
164 esac
165 }
168 todomsg() {
169 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
170 }
173 # Download a file from this mirror
175 download_from() {
176 local i mirrors="$1"
177 shift
178 for i in $mirrors; do
179 case "$i" in
180 http://*|ftp://*|https://*)
181 wget -c $i$@ && break;;
182 *)
183 cp $i/$1 . && break;;
184 esac
185 done
186 }
189 # Download a file trying all mirrors
191 download() {
192 local i
193 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
194 download_from "$i" "$@" && break
195 done
196 }
199 # Execute hooks provided by some packages
201 genisohooks() {
202 local here="$(pwd)"
203 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
204 cd $ROOTFS
205 . $i $ROOTCD
206 done
207 cd "$here"
208 }
211 # Echo the package name if the tazpkg is already installed
213 installed_package_name() {
214 local tazpkg="$1" package VERSION EXTRAVERSION
216 # Try to find package name and version to be able
217 # to repack it from installation
218 # A dash (-) can exist in name *and* in version
219 package=${tazpkg%-*}
220 i=$package
221 while true; do
222 unset VERSION EXTRAVERSION
223 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
224 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
225 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
226 echo $i
227 break
228 fi
229 case "$i" in
230 *-*);;
231 *) break;;
232 esac
233 i=${i%-*}
234 done
235 }
238 # Check for the rootfs tree.
240 check_rootfs() {
241 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
242 }
245 # Check for the boot dir into the root CD tree.
247 verify_rootcd() {
248 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
249 }
251 get() {
252 od -v -j $1 -N ${3:-4} -t u${3:-4} -w${3:-4} -An "$2" 2>/dev/null | sed 's/ *//'
253 }
255 set64() {
256 for i in $(seq 0 8 24 ; seq 24 -8 0); do
257 printf '\\\\x%02X' $((($2 >> $i) & 255))
258 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
259 }
262 # Force the size in the 2nd eltorito boot file (/boot/isolinux/efi.img)
264 fix_efi_boot_img_size() {
265 i=$(stat -m $2/boot/isolinux/boot.cat | sed q)
266 set -- $1 $((102+2048*$i)) $3
267 for i in $(seq 0 8 24); do
268 printf '\\\\x%02X' $((($3 >> $i) & 255))
269 done | xargs echo -en | dd bs=1 conv=notrunc of=$1 seek=$2 2>/dev/null
270 }
273 # Force the size for the /boot/isolinux/efi.img file
275 fix_efi_img_size() {
276 local e=$((0x809C))
277 for i in BOOT ISOLINUX EFI.IMG ; do
278 local sz=$(get $(($e+10)) "$2")
279 e=$(($(get $(($e+2)) "$2") * 2048))
280 while [ $sz -gt 0 ]; do
281 local len=$(get $e "$2" 2)
282 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
283 2>/dev/null)" == "$i" ] && continue 2
284 [ $len -eq 0 ] && break
285 sz=$(($sz-$len))
286 e=$(($e+$len))
287 done
288 return # not found
289 done
290 set64 $(($e+10)) $1 "$2"
291 }
294 # create /boot/isolinux/efi.img to share EFI files with the iso image
296 fixup_uefi_part() {
297 local n
298 [ -s $2/boot/isolinux/efi.img ] || return
300 # Build file list tree
302 ( cd $2 ; find efi -type f -exec echo \
303 'stat -c "$(stat -m {} | sed q) %s f %n" {}' \; | sh | sort -n ) \
304 >/tmp/fatfiles$$
305 n=$(sed 's/ .*//;q' /tmp/fatfiles$$)
306 ( cd $2; find efi ) | awk -v n=$n 'BEGIN { FS="/" }
307 NF > 1 {
308 d[NF $NF]+=2
309 p[NF $NF]=$0
310 b[a++]=NF $NF
311 if (NF>2) d[NF-1 $(NF-1)]++
312 }
313 END {
314 while (a-- > 0) if (d[i=b[a]] > 2) {
315 n-= j =int((d[i]+63)/64)
316 print n " " j*2048 " d " p[i]
317 }
318 print n-1 " 2048 d efi"
319 }' >>/tmp/fatfiles$$
320 sort -n /tmp/fatfiles$$ | awk '{ if (s == 0) s=$1;
321 print ($1-s)+2 " " $2 " " $3 " " $4 }' > /tmp/fatfiles$$.tmp
322 mv -f /tmp/fatfiles$$.tmp /tmp/fatfiles$$
324 # Build fat12 or fat16
326 if [ $(awk '{n+=int(($2+2047)/2048)}END{print n}' /tmp/fatfiles$$) \
327 -lt 4000 ]; then
328 sed '1s/.*/4087 2049 x\n1 1 x/' /tmp/fatfiles$$ | while read c s x; do
329 seq $(($c+1)) $((($s-1)/2048+$c))
330 echo 4095
331 done | awk 'BEGIN { printf "0 "}
332 {
333 if (n == 0) n=$1
334 else {
335 printf "%02X %02X %02X ",n%256,
336 ($1%16)*16+(n/256),$1/16
337 n=0
338 }
339 }
340 END {
341 if (n != 0) printf "FF 0F 00 "
342 print " |"
343 }' | hexdump -R > /tmp/fatbin-12-$$
344 else
345 sed '1s/.*/65527 2049 x\n1 1 x/' /tmp/fatfiles$$ | while read c s x; do
346 seq $(($c+1)) $((($s-1)/2048+$c))
347 echo 65535
348 done | awk 'BEGIN { printf "0 "}
349 {
350 printf "%02X %02X ",$1%256,$1/256
351 }
352 END {
353 print " |"
354 }' | hexdump -R > /tmp/fatbin-16-$$
355 fi
357 # align fat to 512 bytes
358 dd of=$(ls /tmp/fatbin-*-$$) count=0 bs=512 \
359 seek=$((($(stat -c %s /tmp/fatbin-*-$$)-1)/512+1)) 2>/dev/null
361 # build directory records
363 awk '
364 BEGIN {
365 c=2
366 b16="/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0"
367 b14="/0/0/0/0/0/0/0/0/0/0/0/0/0/0"
368 print "EFI /x10" b14 "/x0" c "/0/0/x08/0/0"
369 for (n=i=0; i<63; i++) print b16 b16
370 }
371 {
372 clu[n]=$1
373 size[n]=$2
374 type[n]=$3
375 name[n]=$4
376 n++
377 }
378 END {
379 path="efi"
380 d21="/x10" b14 "/x%02X/x%02X/0/x08/0/0\n"
381 up[0]=0
382 s=1
383 do {
384 l=split(path,x,"/")
385 up[l]=c
386 printf ". " d21,c%256,c/256
387 printf ".. " d21,up[l-1]%256,up[l-1]/256
388 for (i=s,e=2; i<n; i++) {
389 if (substr(name[i],1,length(path)) != path ||
390 split(substr(name[i],length(path)+2),x,"/") > 1)
391 continue
392 split(toupper(x[1]),x,".")
393 if (length(x[1]) >= 8) printf substr(x[1],1,8)
394 else printf x[1] substr(" ",1,8-length(x[1]))
395 if (length(x[2]) >= 3) printf substr(x[2],1,3)
396 else printf x[2] substr(" ",1,3-length(x[2]))
397 if (type[i] == "d") printf "/x10"; else printf "/0"
398 printf b14 "/x%02X/x%02X",clu[i]%256,clu[i]/256
399 printf "/x%02X/x%02X/x%02X/x%02X\n",size[i]%256,
400 (size[i]/256)%256,(size[i]/256/256)%256,
401 size[i]/256/256/256
402 e++
403 }
404 while (e++ < 64) print b16 b16
405 path=name[s]
406 c=clu[s]
407 } while (type[s++] == "d")
408 }' < /tmp/fatfiles$$ | while read line; do
409 echo "$line" | sed 's| |/x20|g;s|/|\\\\|g' | xargs echo -en
410 done > /tmp/fatdir$$
412 # build boot record
414 fat=$(($(stat -c %s /tmp/fatbin-*-$$)/512))
415 r=$((4-($fat+$fat+$(stat -c %s /tmp/fatdir$$)/512)%4))
416 dd if=/dev/zero bs=512 count=$r of=/tmp/fatbr$$ 2> /dev/null
417 echo -en '\x55\xAA' | \
418 dd of=/tmp/fatbr$$ seek=510 bs=1 conv=notrunc 2> /dev/null
419 n=$(stat -m $2/boot/isolinux/efi.img | sed q)
420 fat="$(printf "%02X %02X" $(($fat%256)) $((($fat>>8)%256)))"
421 s=$((($(stat -m $(ls -r $2/boot/rootfs* | sed q) | sed q) - $n)*4))
422 if [ $s -gt 65535 ]; then
423 size="00 00"
424 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
425 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
426 else
427 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
428 size32="00 00 00 00"
429 fi
430 t=32; [ -s /tmp/fatbin-16-$$ ] && t=36
431 hexdump -R <<EOT | dd conv=notrunc of=/tmp/fatbr$$ 2> /dev/null
432 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $r 00 |
433 0 02 40 00 $size f8 $fat 20 00 40 00 00 00 00 00 |
434 0 $size32 80 00 29 00 00 00 00 4e 4f 20 4e 41 |
435 0 4d 45 20 20 20 20 46 41 54 31 $t 20 20 20 cd 18 |
436 0 cd 19 eb fa |
437 EOT
439 # patch efi.img stub
441 cat /tmp/fatbr$$ /tmp/fatbin-*-$$ /tmp/fatbin-*-$$ /tmp/fatdir$$ | \
442 dd of=$1 conv=notrunc bs=2k seek=$n 2>/dev/null
443 fix_efi_img_size $(($s*512)) $1
444 fix_efi_boot_img_size $1 $2 $s
445 rm -f /tmp/fat*$$
447 # Cleanup cache
448 umount $2
449 mount -o loop,ro $1 $2
450 }
453 # allocate efi.img stub to share EFI files in the EFI boot partition
455 alloc_uefi_part() {
456 local basedir=$(dirname "$1")/..
457 local clusters=$({
458 [ -d $basedir/efi ] &&
459 find $basedir/efi -type f -exec stat -c "%s" {} \;
460 while [ -s "$1" ]; do
461 local efifile
462 case "$1" in
463 *taz) efifile=bootia32.efi ;;
464 *taz64) efifile=bootx64.efi ;;
465 esac
466 if [ ! -s $basedir/efi/boot/$efifile ] &&
467 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
468 stat -c "%s" "$1"
469 mkdir -p $basedir/efi/boot 2> /dev/null
470 ln "$1" $basedir/efi/boot/$efifile
471 fi
472 shift
473 done; } | awk '{ n+=int(($1+2047)/2048) } END { print n }')
474 [ ${clusters:-0} -eq 0 ] && return
475 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
476 BEGIN {
477 FS="/"
478 }
479 NF > 1 {
480 d[NF $NF]+=2
481 d[NF-1 $(NF-1)]++
482 }
483 END {
484 for (i in d)
485 n+=int((d[i]+63)/64)
486 print n
487 }')
488 clusters=$(($clusters+$dclust))
489 if [ $clusters -lt 4000 ]; then
490 # reserved + fat*2 + root dir + dirs
491 count=$(((1 + (($clusters*3+1023)/1024)*2+3)/4+1 + $dclust ))
492 else
493 # reserved + fat*2 + root dir + dirs
494 count=$(((1 + (($clusters+255)/256)*2+3)/4 + 1 + $dclust ))
495 fi
496 dd if=/dev/zero bs=2k of=$basedir/boot/isolinux/efi.img \
497 count=$count 2> /dev/null
498 }
501 # isolinux.conf doesn't know the kernel version.
502 # We name the kernel image 'bzImage'.
503 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
505 make_bzImage_hardlink() {
506 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
507 rm -f ${1:-.}/bzImage 2>/dev/null
508 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
509 fi
510 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
511 rm -f ${1:-.}/bzImage64 2> /dev/null
512 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
513 fi
514 }
517 create_iso() {
518 cd $2
519 deduplicate
521 rm -rf $2/boot/grub*
522 make_bzImage_hardlink $2/boot
523 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
525 cat > /tmp/cdsort$$ <<EOT
526 $PWD/boot/isolinux 100
527 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
528 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
529 $(find $PWD/efi -type f 2>/dev/null | awk 'BEGIN{n=299} { print $1 " " n-- }')
530 $PWD/boot/isolinux/efi.img 300
531 $PWD/boot/isolinux/isolinux.bin 399
532 $PWD/boot/isolinux/boot.cat 400
533 EOT
535 action 'Computing md5...'
536 touch boot/isolinux/boot.cat
537 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
538 sort -k 2 > md5sum
539 status
541 cd - >/dev/null
542 title 'Generating ISO image'
544 _ 'Generating %s' "$1"
545 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
546 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
547 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
548 -no-emul-boot -boot-load-size 4 -boot-info-table \
549 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
550 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
551 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
552 -A "tazlito $VERSION/$(genisoimage --version)" \
553 -copyright README -P "www.slitaz.org" -no-pad $2
554 rm -f /tmp/cdsort$$
555 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
557 mkdir /tmp/mnt$$
558 mount -o loop,ro $1 /tmp/mnt$$
559 fixup_uefi_part $1 /tmp/mnt$$
560 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
561 ${uefi:+boot/isolinux/efi.img} ; do
562 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
563 done
564 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
565 seek=$(stat -m /tmp/mnt$$/md5sum | sed q) 2> /dev/null
566 umount -d /tmp/mnt$$
567 rmdir /tmp/mnt$$
569 if [ -s '/etc/tazlito/info' ]; then
570 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
571 action 'Storing ISO info...'
572 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
573 status
574 fi
575 fi
577 if [ -x '/usr/bin/isohybrid' ]; then
578 action 'Creating hybrid ISO...'
579 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
580 status
581 fi
583 if [ -x '/usr/bin/iso2exe' ]; then
584 echo 'Creating EXE header...'
585 /usr/bin/iso2exe $1 2>/dev/null
586 fi
587 }
590 # Generate a new ISO image using isolinux.
592 gen_livecd_isolinux() {
593 # Some packages may want to alter iso
594 genisohooks iso
595 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
597 # Set date for boot msg.
598 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
599 DATE=$(date +%Y%m%d)
600 action 'Setting build date to: %s...' "$DATE"
601 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
602 status
603 fi
605 cd $DISTRO
606 create_iso $ISO_NAME.iso $ROOTCD
608 action 'Creating the ISO md5sum...'
609 md5sum $ISO_NAME.iso > $ISO_NAME.md5
610 status
612 separator
613 # Some packages may want to alter final iso
614 genisohooks final
615 }
618 lzma_history_bits() {
619 #
620 # This generates an ISO which boots with Qemu but gives
621 # rootfs errors in frugal or liveUSB mode.
622 #
623 # local n
624 # local sz
625 # n=20 # 1Mb
626 # sz=$(du -sk $1 | cut -f1)
627 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
628 # n=$(( $n + 1 ))
629 # sz=$(( $sz / 2 ))
630 # done
631 # echo $n
632 echo ${LZMA_HISTORY_BITS:-24}
633 }
636 lzma_switches() {
637 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
638 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
639 }
642 lzma_set_size() {
643 # Update size field for lzma'd file packed using -si switch
644 return # Need to fix kernel code?
646 local n i
647 n=$(unlzma < $1 | wc -c)
648 for i in $(seq 1 8); do
649 printf '\\\\x%02X' $(($n & 255))
650 n=$(($n >> 8))
651 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
652 }
655 align_to_32bits() {
656 local size=$(stat -c %s ${1:-/dev/null})
657 [ $((${size:-0} & 3)) -ne 0 ] &&
658 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
659 }
662 dogzip() {
663 gzip -9 > $1
664 [ -x /usr/bin/advdef ] && advdef -qz4 $1
665 }
668 # Pack rootfs
670 pack_rootfs() {
671 ( cd $1; find . -print | cpio -o -H newc ) | \
672 case "$COMPRESSION" in
673 none)
674 _ 'Creating %s without compression...' 'initramfs'
675 cat > $2
676 ;;
677 gzip)
678 _ 'Creating %s with gzip compression...' 'initramfs'
679 dogzip $2
680 ;;
681 *)
682 _ 'Creating %s with lzma compression...' 'initramfs'
683 lzma e -si -so $(lzma_switches $1) > $2
684 lzma_set_size $2
685 ;;
686 esac
687 align_to_32bits $2
688 echo 1 > /tmp/rootfs
689 }
692 # Compression functions for writeiso.
694 write_initramfs() {
695 case "$COMPRESSION" in
696 lzma)
697 _n 'Creating %s with lzma compression...' "$INITRAMFS"
698 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
699 align='y'
700 lzma_set_size "/$INITRAMFS"
701 ;;
702 gzip)
703 _ 'Creating %s with gzip compression...' "$INITRAMFS"
704 cpio -o -H newc | dogzip "/$INITRAMFS"
705 ;;
706 *)
707 # align='y'
708 _ 'Creating %s without compression...' "$INITRAMFS"
709 cpio -o -H newc > "/$INITRAMFS"
710 ;;
711 esac < /tmp/list
712 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
713 echo 1 > /tmp/rootfs
714 }
717 # Deduplicate files (MUST be on the same filesystem).
719 deduplicate() {
720 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
721 (
722 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
723 while read attr inode link file; do
724 [ -L "$file" ] && continue
725 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
726 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
727 rm -f "$file"
728 if ln "$old_file" "$file" 2>/dev/null; then
729 inode="$old_inode"
730 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
731 save="$(($save+(${attr%%-*}+512)/1024))"
732 else
733 cp -a "$old_file" "$file"
734 fi
735 fi
736 fi
737 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
738 done
739 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
740 )
742 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
743 (
744 old_attr=""; hardlinks=0;
745 while read attr inode link file; do
746 attr="${attr/-TARGET-/-$(readlink $file)}"
747 if [ "$attr" == "$old_attr" ]; then
748 if [ "$inode" != "$old_inode" ]; then
749 rm -f "$file"
750 if ln "$old_file" "$file" 2>/dev/null; then
751 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
752 else
753 cp -a "$old_file" "$file"
754 fi
755 fi
756 else
757 old_file="$file"
758 old_attr="$attr"
759 old_inode="$inode"
760 fi
761 done
762 _ '%s duplicate symlinks.' "$hardlinks"
763 )
764 }
767 # Generate a new initramfs from the root filesystem.
769 gen_initramfs() {
770 # Just in case CTRL+c
771 rm -f $DISTRO/gen
773 # Some packages may want to alter rootfs
774 genisohooks rootfs
775 cd $1
777 # Normalize file time
778 find $1 -newer $1 -exec touch -hr $1 {} \;
780 # Link duplicate files
781 deduplicate
783 # Use lzma if installed. Display rootfs size in realtime.
784 rm -f /tmp/rootfs 2>/dev/null
785 pack_rootfs . $DISTRO/$(basename $1).gz &
786 sleep 2
787 echo -en "\nFilesystem size:"
788 while [ ! -f /tmp/rootfs ]; do
789 sleep 1
790 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
791 done
792 echo -e "\n"
793 rm -f /tmp/rootfs
794 cd $DISTRO
795 mv $(basename $1).gz $ROOTCD/boot
796 }
799 distro_sizes() {
800 if [ -n "$start_time" ]; then
801 time=$(($(date +%s) - $start_time))
802 sec=$time
803 div=$(( ($time + 30) / 60))
804 [ "$div" -ne 0 ] && min="~ ${div}m"
805 _ 'Build time : %ss %s' "$sec" "$min"
806 fi
807 cat <<EOT
808 Build date : $(date +%Y%m%d)
809 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
810 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
811 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
812 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
813 EOT
814 footer "Image is ready: $ISO_NAME.iso"
815 }
818 # Print ISO and rootfs size.
820 distro_stats() {
821 title 'Distro statistics: %s' "$DISTRO"
822 distro_sizes
823 }
826 # Create an empty configuration file.
828 empty_config_file() {
829 cat >> tazlito.conf <<"EOF"
830 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
831 #
833 # Name of the ISO image to generate.
834 ISO_NAME=""
836 # ISO image volume name.
837 VOLUM_NAME="SliTaz"
839 # Name of the preparer.
840 PREPARED="$USER"
842 # Path to the packages repository and the packages.list.
843 PACKAGES_REPOSITORY=""
845 # Path to the distro tree to gen-distro from a list of packages.
846 DISTRO=""
848 # Path to the directory containing additional files
849 # to copy into the rootfs and rootcd of the LiveCD.
850 ADDFILES="$DISTRO/addfiles"
852 # Default answer for binary question (Y or N)
853 DEFAULT_ANSWER="ASK"
855 # Compression utility (lzma, gzip or none)
856 COMPRESSION="lzma"
857 EOF
858 }
861 # Extract rootfs.gz somewhere
863 extract_rootfs() {
864 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
865 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
866 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
867 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
868 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
869 }
872 # Extract flavor file to temp directory
874 extract_flavor() {
875 # Input: $1 - flavor name to extract;
876 # $2 = absent/empty: just extract 'outer layer'
877 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
878 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
879 # Output: temp dir path where flavor was extracted
880 local f="$1.flavor" from to infos="$1.desc"
881 [ -f "$f" ] || die "File '$f' not found"
882 local dir="$(mktemp -d)"
883 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
885 if [ -n "$2" ]; then
886 cd $dir
888 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
890 for i in rootcd rootfs; do
891 [ -f "$1.$i" ] || continue
892 mkdir "$i"
893 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
894 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
895 rm "$1.$i"
896 done
897 touch -t 197001010100.00 "$1.*"
898 # Info to be stored inside ISO
899 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
900 rm $1.list*
902 # Renames
903 while read from to; do
904 [ -f "$from" ] || continue
905 mv "$from" "$to"
906 done <<EOT
907 $1.nonfree non-free.list
908 $1.pkglist packages.list
909 $1-distro.sh distro.sh
910 $1.receipt receipt
911 $1.mirrors mirrors
912 $1.desc description
913 EOT
914 fi
916 echo $dir
917 }
920 # Pack flavor file from temp directory
922 pack_flavor() {
923 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
924 }
927 # Remove duplicate files
929 files_match() {
930 if [ -d "$1" ]; then
931 return 1
933 elif [ -L "$1" ] && [ -L "$2" ]; then
934 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
936 elif [ -f "$1" ] && [ -f "$2" ]; then
937 cmp -s "$1" "$2" && return 0
939 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
940 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
941 return 0
943 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
944 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
945 return 0
947 fi 2> /dev/null
948 return 1
949 }
951 remove_with_path() {
952 dir="$(dirname $1)"
953 rm -f "$1"
954 while rmdir "$dir" 2> /dev/null; do
955 dir="$(dirname $dir)"
956 done
957 }
959 mergefs() {
960 # Note, many packages have files with spaces in the name
961 IFS=$'\n'
963 local size1=$(du -hs "$1" | awk '{ print $1 }')
964 local size2=$(du -hs "$2" | awk '{ print $1 }')
965 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
967 # merge symlinks files and devices
968 ( cd "$1"; find ) | \
969 while read file; do
970 files_match "$1/$file" "$2/$file" "$file" &&
971 remove_with_path "$2/$file"
972 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
973 done
975 unset IFS
976 status
977 }
980 cleanup_merge() {
981 rm -rf $TMP_DIR
982 exit 1
983 }
986 # Update isolinux config files for multiple rootfs
988 update_bootconfig() {
989 local files
990 action 'Updating boot config files...'
991 files="$(grep -l 'include common' $1/*.cfg)"
992 for file in $files; do
993 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
994 if (/label/) label=$0;
995 else if (/kernel/) kernel=$0;
996 else if (/append/) {
997 i=index($0,"rootfs.gz");
998 append=substr($0,i+9);
999 }
1000 else if (/include/) {
1001 for (i = 1; i <= n; i++) {
1002 print label i
1003 print kernel;
1004 initrd="initrd=/boot/rootfs" n ".gz"
1005 for (j = n - 1; j >= i; j--) {
1006 initrd=initrd ",/boot/rootfs" j ".gz";
1008 printf "\tappend %s%s\n",initrd,append;
1009 print "";
1011 print;
1013 else print;
1014 }' < $file > $file.$$
1015 mv -f $file.$$ $file
1016 done
1017 sel="$(echo $2 | awk '{
1018 for (i=1; i<=NF; i++)
1019 if (i % 2 == 0) printf " slitaz%d", i/2
1020 else printf " %s", $i
1021 }')"
1023 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1025 label slitaz
1026 kernel /boot/isolinux/ifmem.c32
1027 append$sel noram
1029 label noram
1030 config noram.cfg
1032 EOT
1034 # Update vesamenu
1035 if [ -s "$1/isolinux.cfg" ]; then
1036 files="$files $1/isolinux.cfg"
1037 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1038 BEGIN {
1039 kernel = " COM32 c32box.c32"
1042 if (/ROWS/) print "MENU ROWS " n+$3;
1043 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1044 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1045 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1046 else if (/VSHIFT/) {
1047 x = $3-n;
1048 if (x < 0) x = 0;
1049 print "MENU VSHIFT " x;
1051 else if (/rootfs.gz/) {
1052 linux = "";
1053 if (/bzImage/) linux = "linux /boot/bzImage ";
1054 i = index($0, "rootfs.gz");
1055 append = substr($0, i+9);
1056 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1057 printf "\tappend%s noram\n", sel;
1058 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1059 for (i = 1; i <= n; i++) {
1060 print "LABEL slitaz" i
1061 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1062 printf "%s\n", kernel;
1063 initrd = "initrd=/boot/rootfs" n ".gz"
1064 for (j = n - 1; j >= i; j--) {
1065 initrd = initrd ",/boot/rootfs" j ".gz";
1067 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1070 else if (/bzImage/) kernel = $0;
1071 else print;
1072 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1073 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1074 fi
1076 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1077 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1078 cat > $1/noram.cfg <<EOT
1079 implicit 0
1080 prompt 1
1081 timeout 80
1082 $(grep '^F[0-9]' $1/isolinux.cfg)
1084 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1085 say Not enough RAM to boot slitaz. Trying hacker mode...
1086 default hacker
1087 label hacker
1088 KERNEL /boot/bzImage
1089 append rw root=/dev/null vga=normal
1091 label reboot
1092 EOT
1094 if [ -s $1/c32box.c32 ]; then
1095 cat >> $1/noram.cfg <<EOT
1096 COM32 c32box.c32
1097 append reboot
1099 label poweroff
1100 COM32 c32box.c32
1101 append poweroff
1103 EOT
1104 else
1105 echo " com32 reboot.c32" >> $1/noram.cfg
1106 fi
1108 # Restore real label names
1109 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1110 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1111 while read pat; do
1112 sed -i "s/slitaz$pat/" $files
1113 done
1114 status
1118 # Uncompress rootfs or module to stdout
1120 uncompress() {
1121 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1122 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1126 # Install a missing package
1128 install_package() {
1129 if [ -z "$2" ]; then
1130 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1131 else
1132 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1133 fi
1134 case "$answer" in
1135 y)
1136 # We don't want package on host cache.
1137 action 'Getting and installing package: %s' "$1"
1138 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1139 status ;;
1140 *)
1141 return 1 ;;
1142 esac
1146 # Check iso for loram transformation
1148 check_iso_for_loram() {
1149 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1150 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1154 # Build initial rootfs for loram ISO ram/cdrom/http
1156 build_initfs() {
1157 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1158 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1159 mirror3.slitaz.org mirror.slitaz.org"
1160 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1161 [ -z "$version" ] && die "Can't find the kernel version." \
1162 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1164 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1165 need_lib=false
1166 for i in bin dev run mnt proc tmp sys lib/modules; do
1167 mkdir -p $TMP_DIR/initfs/$i
1168 done
1169 ln -s bin $TMP_DIR/initfs/sbin
1170 ln -s . $TMP_DIR/initfs/usr
1171 for aufs in aufs overlayfs; do
1172 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1173 install_package linux-$aufs $version && break
1174 install_package $aufs $version && break
1175 done || return 1
1176 [ -s /init ] || install_package slitaz-boot-scripts
1177 cp /init $TMP_DIR/initfs/
1178 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1179 $TMP_DIR/initfs/lib/modules
1180 if [ "$1" == 'cdrom' ]; then
1181 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1182 else
1183 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1184 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1185 install_package linux-squashfs $version || return 1
1186 done
1187 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1188 $TMP_DIR/initfs/lib/modules
1189 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1190 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1191 fi
1192 if [ "$1" == 'http' ]; then
1193 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1194 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1195 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1196 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1197 cp -a /dev/fuse $TMP_DIR/initfs/dev
1198 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1199 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1200 else
1201 need_lib=true
1202 fi
1203 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1204 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1205 else
1206 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1207 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1208 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1209 cp -a /lib/librt* $TMP_DIR/initfs/lib
1210 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1211 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1212 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1213 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1214 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1215 need_lib=true
1216 fi
1217 cd $TMP_DIR/fs
1218 echo 'Getting slitaz-release & ethernet modules...'
1219 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1220 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1221 [ -s rootfs* ] || continue
1222 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1223 rm -f rootfs*
1224 done 2>&1 > /dev/null
1225 cd - > /dev/null
1226 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1227 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1228 -type f -name '*.ko*' | while read mod; do
1229 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1230 uncompress $mod > $f
1231 grep -q alias=pci: $f || rm -f $f
1232 done
1233 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1234 f=$(basename $i)..z
1235 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1236 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1237 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1238 for j in $deps; do
1239 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1240 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1241 done
1242 done
1243 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"
1244 _n 'List of URLs to insert: '
1245 read -t 30 urliso2
1246 urliso="$urliso2 $urliso"
1247 fi
1248 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1249 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1250 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1251 else
1252 cp /bin/busybox $TMP_DIR/initfs/bin
1253 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1254 cp /sbin/insmod $TMP_DIR/initfs/bin
1255 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1256 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1257 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1258 fi
1259 need_lib=true
1260 fi
1261 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1262 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1263 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1264 done
1265 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1266 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1267 $TMP_DIR/initfs/lib/modules 2>/dev/null
1268 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1269 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1270 cp -a $i $TMP_DIR/initfs/dev
1271 done
1272 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1273 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1274 cp -a $i $TMP_DIR/initfs/dev
1275 done 2>/dev/null
1276 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1277 cp -a $i $TMP_DIR/initfs/lib
1278 done
1279 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1280 #!/bin/sh
1282 getarg() {
1283 grep -q " \$1=" /proc/cmdline || return 1
1284 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1285 return 0
1288 copy_rootfs() {
1289 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1290 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1291 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1292 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1293 path=/mnt/
1294 return 0
1295 else
1296 rm -f /mnt/rootfs*
1297 return 1
1298 fi
1301 echo "Switching / to tmpfs..."
1302 mount -t proc proc /proc
1303 size="\$(grep rootfssize= < /proc/cmdline | \\
1304 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1305 [ -n "\$size" ] || size="-o size=90%"
1307 mount -t sysfs sysfs /sys
1308 for i in /lib/modules/*.ko ; do
1309 echo -en "Probe \$i \\r"
1310 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1311 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1312 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1313 insmod /lib/modules/\$k.ko 2> /dev/null
1314 done
1315 echo "Loading \$i"
1316 insmod \$i 2> /dev/null
1317 break
1318 done
1319 done
1320 umount /sys
1321 while read var default; do
1322 eval \$var=\$default
1323 getarg \$var \$var
1324 done <<EOT
1325 eth eth0
1326 dns 208.67.222.222,208.67.220.220
1327 netmask 255.255.255.0
1328 gw
1329 ip
1330 EOT
1331 grep -q \$eth /proc/net/dev || sh
1332 if [ -n "\$ip" ]; then
1333 ifconfig \$eth \$ip netmask \$netmask up
1334 route add default gateway \$gw
1335 for i in \$(echo \$dns | sed 's/,/ /g'); do
1336 echo "nameserver \$i" >> /etc/resolv.conf
1337 done
1338 else
1339 udhcpc -f -q -s /lib/udhcpc -i \$eth
1340 fi
1341 for i in $urliso ; do
1342 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1343 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"
1344 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1345 done
1346 getarg urliso URLISO
1347 DIR=fs
1348 if getarg loram DIR; then
1349 DEVICE=\${DIR%,*}
1350 DIR=/\${DIR#*,}
1351 fi
1352 mount -t tmpfs \$size tmpfs /mnt
1353 path2=/mnt/.httpfs/
1354 path=/mnt/.cdrom/
1355 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1356 while [ ! -d \$path/boot ]; do
1357 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1358 httpfs \$i \$path2 && echo \$i && break
1359 done
1360 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1361 done
1363 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1364 umount /proc
1365 branch=:/mnt/.cdrom/\$DIR
1366 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1367 branch=
1368 lp=1
1369 insmod /lib/modules/squashfs.ko 2> /dev/null
1370 for i in \${path}boot/rootfs?.* ; do
1371 fs=\${i#*root}
1372 branch=\$branch:/mnt/.\$fs
1373 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1374 losetup -o 124 /dev/loop\$lp \$i
1375 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1376 lp=\$((\$lp+1))
1377 done
1378 fi
1379 mkdir -p /mnt/.rw/mnt/.httpfs
1380 while read type opt; do
1381 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1382 done <<EOT
1383 aufs br=/mnt/.rw\$branch
1384 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1385 EOT
1386 rm -rf /lib/modules
1387 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1388 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1389 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1390 EOTEOT
1391 chmod +x $TMP_DIR/initfs/init
1392 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1393 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1394 rm -f $i
1395 done 2>/dev/null
1396 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1397 lzma e $TMP_DIR/initfs.gz -si
1398 lzma_set_size $TMP_DIR/initfs.gz
1399 rm -rf $TMP_DIR/initfs
1400 align_to_32bits $TMP_DIR/initfs.gz
1401 return 0
1405 # Move each initramfs to squashfs
1407 build_loram_rootfs() {
1408 rootfs_sizes=""
1409 for i in $TMP_DIR/iso/boot/rootfs*; do
1410 mkdir -p $TMP_DIR/fs
1411 cd $TMP_DIR/fs
1412 uncompress $i | cpio -idm
1413 deduplicate
1414 cd - > /dev/null
1415 rootfs=$TMP_DIR/$(basename $i)
1416 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1417 cd $TMP_DIR
1418 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1419 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1420 rm -f $rootfs
1421 mv $rootfs.cpio $rootfs
1422 cd - > /dev/null
1423 rm -rf $TMP_DIR/fs
1424 done
1428 # Move meta boot configuration files to basic configuration files
1429 # because meta loram flavor is useless when rootfs is not loaded in RAM
1431 unmeta_boot() {
1432 local root=${1:-$TMP_DIR/loramiso}
1433 if [ -f $root/boot/isolinux/noram.cfg ]; then
1434 # We keep enough information to do unloram...
1435 [ -s $root/boot/isolinux/common.cfg ] &&
1436 sed -i 's/label slitaz/label orgslitaz/' \
1437 $root/boot/isolinux/common.cfg
1438 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1439 shift
1440 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1441 $root/boot/isolinux/isolinux.cfg
1442 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1443 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1444 $root/boot/isolinux/*.cfg
1445 fi
1449 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1450 # These squashfs may be loaded in RAM at boot time.
1451 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1452 # Meta flavors are converted to normal flavors.
1454 build_loram_cdrom() {
1455 build_initfs cdrom || return 1
1456 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1457 mkdir $TMP_DIR/loramiso/fs
1458 cd $TMP_DIR/loramiso/fs
1459 for i in $( ls ../boot/root* | sort -r ) ; do
1460 uncompress $i | cpio -idmu
1461 rm -f $i
1462 done
1463 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1464 cd - >/dev/null
1465 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1466 unmeta_boot
1467 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1468 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1469 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1470 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1471 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1472 create_iso $OUTPUT $TMP_DIR/loramiso
1476 # Create http bootstrap to load and remove loram_cdrom
1477 # Meta flavors are converted to normal flavors.
1479 build_loram_http() {
1480 build_initfs http || return 1
1481 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1482 rm -f $TMP_DIR/loramiso/boot/rootfs*
1483 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1484 unmeta_boot
1485 create_iso $OUTPUT $TMP_DIR/loramiso
1489 # Update meta flavor selection sizes.
1490 # Reduce sizes with rootfs gains.
1492 update_metaiso_sizes() {
1493 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1494 do
1495 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1496 local sizes="$rootfs_sizes"
1497 local new
1498 set -- $append
1499 shift
1500 [ "$1" == "ifmem" ] && shift
1501 new=""
1502 while [ -n "$2" ]; do
1503 local s
1504 case "$1" in
1505 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1506 *M) s=$(( ${1%M} * 1024 ));;
1507 *) s=${1%K};;
1508 esac
1509 sizes=${sizes#* }
1510 for i in $sizes ; do
1511 s=$(( $s - $i ))
1512 done
1513 new="$new $s $2"
1514 shift 2
1515 done
1516 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1517 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1518 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1519 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1520 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1521 done
1525 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1526 # Meta flavor selection sizes are updated.
1528 build_loram_ram() {
1529 build_initfs ram || return 1
1530 build_loram_rootfs "$1"
1531 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1532 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1533 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1534 update_metaiso_sizes
1535 create_iso $OUTPUT $TMP_DIR/loramiso
1539 # Remove files installed by packages
1541 find_flavor_rootfs() {
1542 for i in $1/etc/tazlito/*.extract; do
1543 [ -e $i ] || continue
1544 chroot $1 /bin/sh ${i#$1}
1545 done
1547 # Clean hardlinks and files patched by genisofs in /boot
1548 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1549 rm -f $1/boot/$i*
1550 done
1552 # Clean files generated in post_install
1553 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1554 $1/dev/core $1/dev/fd $1/dev/std*
1556 # Verify md5
1557 cat $1$INSTALLED/*/md5sum | \
1558 while read md5 file; do
1559 [ -e "$1$file" ] || continue
1560 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1561 rm -f "$1$file"
1562 done
1564 # Check configuration files
1565 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1566 [ -e $i ] || continue
1567 mkdir /tmp/volatile$$
1568 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1569 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1570 while read file ; do
1571 [ -e "$1/$file" ] || continue
1572 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1573 done
1574 rm -rf /tmp/volatile$$
1575 done
1577 # Remove other files blindly
1578 for i in $1$INSTALLED/*/files.list; do
1579 for file in $(cat "$i"); do
1580 [ "$1$file" -nt "$i" ] && continue
1581 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1582 [ -d "$1$file" ] || rm -f "$1$file"
1583 done
1584 done
1586 # Remove tazpkg files and tmp files
1587 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1588 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1589 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1590 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1591 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1593 # Cleanup directory tree
1594 cd $1
1595 find * -type d | sort -r | while read dir; do
1596 rmdir "$dir" 2>/dev/null
1597 done
1598 cd - > /dev/null
1602 # Get byte(s) from a binary file
1604 get() {
1605 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1609 # Get cpio flavor info from the ISO image
1611 flavordata() {
1612 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1613 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1617 # Restore undigest mirrors
1619 restore_mirrors() {
1620 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1621 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1623 action 'Restoring mirrors...'
1624 if [ -d "$undigest.bak" ]; then
1625 [ -d "$undigest" ] && rm -r "$undigest"
1626 mv "$undigest.bak" "$undigest"
1627 fi
1628 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1629 :; status
1633 # Setup undigest mirrors
1635 setup_mirrors() {
1636 # Setup mirrors in plain system or in chroot (with variable root=)
1637 local mirrorlist="$1" fresh repacked
1638 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1640 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1641 restore_mirrors
1643 _ 'Setting up mirrors for %s...' "$root/"
1644 # Backing up current undigest mirrors and priority
1645 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1646 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1647 rm -rf '/var/www/tazlito/'
1648 mkdir -p '/var/www/tazlito/'
1650 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1651 fresh='/home/slitaz/packages'
1652 if [ -d "$fresh" ]; then
1653 # Setup first undigest mirror
1654 mkdir -p "$undigest/fresh"
1655 echo "$fresh" > "$undigest/fresh/mirror"
1656 echo 'fresh' >> "$priority"
1657 # Rebuild mirror DB if needed
1658 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1659 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1660 tazpkg mkdb "$fresh" --forced --root=''
1661 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1662 fi
1664 # Repacked packages: high priority
1665 repacked="$PACKAGES_REPOSITORY"
1666 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1667 # According to Tazlito setup file (tazlito.conf):
1668 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1669 # or
1670 # WORK_DIR="/home/slitaz"
1671 # and
1672 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1673 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1675 # Setup second undigest mirror
1676 mkdir -p "$undigest/repacked"
1677 echo "$repacked" > "$undigest/repacked/mirror"
1678 echo 'repacked' >> "$priority"
1679 # Rebuild mirror DB if needed
1680 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1681 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1682 tazpkg mkdb "$repacked" --forced --root=''
1683 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1684 fi
1686 # All repositories listed in mirrors list: normal priority
1687 [ -e "$mirrorlist" ] && \
1688 while read mirror; do
1689 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1690 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1691 mkdir -p "$undigest/$mirrorid"
1692 echo "$mirror" > "$undigest/$mirrorid/mirror"
1693 echo "$mirrorid" >> "$priority"
1694 done < "$mirrorlist"
1696 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1698 # Show list of mirrors
1699 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1700 function show(num, name, url) {
1701 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1704 num++;
1705 "cat " db "/undigest/" $0 "/mirror" | getline url;
1706 show(num, $0, url);
1708 END {
1709 num++;
1710 "cat " db "/mirror" | getline url;
1711 show(num, "main", url);
1712 }' "$priority"
1714 tazpkg recharge --quiet >/dev/null
1718 # Get list of 'packages.info' lists using priority
1720 pi_lists() {
1721 local pi
1722 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1723 local priority="$root$LOCALSTATE/priority"
1724 local undigest="$root$LOCALSTATE/undigest"
1727 [ -s "$priority" ] && cat "$priority"
1728 echo 'main'
1729 [ -d "$undigest" ] && ls "$undigest"
1730 } | awk -vun="$undigest/" '
1732 if (arr[$0] != 1) {
1733 arr[$0] = 1;
1734 print un $0 "/packages.info";
1736 }' | sed 's|/undigest/main||' | \
1737 while read pi; do
1738 [ -e "$pi" ] && echo "$pi"
1739 done
1743 # Strip versions from packages list
1745 strip_versions() {
1746 if [ -n "$stripped" ]; then
1747 action 'Consider list %s already stripped' "$(basename "$1")"
1748 status
1749 return 0
1750 fi
1751 action 'Strip versions from list %s...' "$(basename "$1")"
1752 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1753 [ -f "$in_list" ] || die "List '$in_list' not found."
1755 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1756 awk '
1758 if (FILENAME ~ "packages.info") {
1759 # Collect package names
1760 FS = "\t"; pkg[$1] = 1;
1761 } else {
1762 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1763 while (NF > 1 && ! pkg[$0])
1764 NF --;
1765 printf "%s\n", $0;
1767 }' $(pi_lists) "$in_list" > "$tmp_list"
1769 cat "$tmp_list" > "$in_list"
1770 rm "$tmp_list"
1771 status
1775 # Display list of unknown packages (informative)
1777 display_unknown() {
1778 [ -s "$1" ] || return
1779 echo "Unknown packages:" >&2
1780 cat "$1" >&2
1781 rm "$1"
1785 # Display warnings about critical packages absent (informative)
1787 display_warn() {
1788 [ -s "$1" ] || return
1789 echo "Absent critical packages:" >&2
1790 cat "$1" >&2
1791 rm "$1"
1792 echo "Probably ISO image will be unusable."
1796 # Install packages to rootfs
1798 install_list_to_rootfs() {
1799 local list="$1" rootfs="$2" pkg i ii
1800 local undigest="$rootfs/var/lib/tazpkg/undigest"
1802 # initial tazpkg setup in empty rootfs
1803 tazpkg --root=$rootfs >/dev/null 2>&1
1804 # pass current 'mirror' to the rootfs
1805 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1806 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1807 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1808 # link rootfs packages cache to the regular packages cache
1809 rm -r "$rootfs/var/cache/tazpkg"
1810 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1812 setup_mirrors mirrors
1814 # Just in case if flavor doesn't contain "tazlito" package
1815 mkdir -p "$rootfs/etc/tazlito"
1817 newline
1819 # Choose detailed log with --detailed
1820 if [ -n "$detailed" ]; then
1821 while read pkg; do
1822 separator '-'
1823 echo $pkg
1824 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1825 done < $list
1826 separator '='
1827 else
1828 while read pkg; do
1829 action 'Installing package: %s' "$pkg"
1830 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1831 status
1832 done < $list
1833 fi
1834 newline
1836 restore_mirrors
1837 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1838 for i in fresh repacked; do
1839 ii="$undigest/$i"
1840 [ -d "$ii" ] && rm -rf "$ii"
1841 ii="$rootfs/var/lib/tazpkg/priority"
1842 if [ -f "$ii" ]; then
1843 sed -i "/$i/d" "$ii"
1844 [ -s "$ii" ] || rm "$ii"
1845 fi
1846 done
1847 [ -d "$undigest" ] && \
1848 for i in $(find "$undigest" -type f); do
1849 # Remove all undigest PKGDB files but 'mirror'
1850 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1851 done
1852 [ -d "$undigest" ] && \
1853 rmdir --ignore-fail-on-non-empty "$undigest"
1855 # Un-link packages cache
1856 rm "$rootfs/var/cache/tazpkg"
1858 # Clean /var/lib/tazpkg
1859 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1865 ####################
1866 # Tazlito commands #
1867 ####################
1869 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1870 case "$0" in
1871 *reduplicate)
1872 find ${@:-.} ! -type d -links +1 \
1873 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1874 exit 0 ;;
1875 *deduplicate)
1876 deduplicate "$@"
1877 exit 0 ;;
1878 esac
1881 case "$COMMAND" in
1882 stats)
1883 # Tazlito general statistics from the config file.
1885 title 'Tazlito statistics'
1886 optlist "\
1887 Config file : $CONFIG_FILE
1888 ISO name : $ISO_NAME.iso
1889 Volume name : $VOLUM_NAME
1890 Prepared : $PREPARED
1891 Packages repository : $PACKAGES_REPOSITORY
1892 Distro directory : $DISTRO
1893 Additional files : $ADDFILES
1894 " | sed '/: $/d'
1895 footer
1896 ;;
1899 list-addfiles)
1900 # Simple list of additional files in the rootfs
1901 newline
1902 if [ -d "$ADDFILES/rootfs" ]; then
1903 cd $ADDFILES
1904 find rootfs -type f
1905 else
1906 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1907 fi
1908 newline
1909 ;;
1912 gen-config)
1913 # Generate a new config file in the current dir or the specified
1914 # directory by $2.
1916 if [ -n "$2" ]; then
1917 mkdir -p "$2" && cd "$2"
1918 fi
1920 newline
1921 action 'Generating empty tazlito.conf...'
1922 empty_config_file
1923 status
1925 separator
1926 if [ -f 'tazlito.conf' ] ; then
1927 _ 'Configuration file is ready to edit.'
1928 _ 'File location: %s' "$(pwd)/tazlito.conf"
1929 newline
1930 fi
1931 ;;
1934 configure)
1935 # Configure a tazlito.conf config file. Start by getting
1936 # a empty config file and sed it.
1938 if [ -f 'tazlito.conf' ]; then
1939 rm tazlito.conf
1940 else
1941 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1942 'or in the same directory of the file you want to configure.'
1943 cd /etc
1944 fi
1946 empty_config_file
1948 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1950 # ISO name.
1951 echo -n "ISO name : " ; read answer
1952 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1953 # Volume name.
1954 echo -n "Volume name : " ; read answer
1955 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1956 # Packages repository.
1957 echo -n "Packages repository : " ; read answer
1958 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1959 # Distro path.
1960 echo -n "Distro path : " ; read answer
1961 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1962 footer "Config file is ready to use."
1963 echo 'You can now extract an ISO or generate a distro.'
1964 newline
1965 ;;
1968 gen-iso)
1969 # Simply generate a new iso.
1971 check_root
1972 verify_rootcd
1973 gen_livecd_isolinux
1974 distro_stats
1975 ;;
1978 gen-initiso)
1979 # Simply generate a new initramfs with a new iso.
1981 check_root
1982 verify_rootcd
1983 gen_initramfs "$ROOTFS"
1984 gen_livecd_isolinux
1985 distro_stats
1986 ;;
1989 extract-distro)
1990 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1992 check_root
1993 ISO_IMAGE="$2"
1994 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1995 'Example:\n tazlito image.iso /path/target'
1997 # Set the distro path by checking for $3 on cmdline.
1998 TARGET="${3:-$DISTRO}"
2000 # Exit if existing distro is found.
2001 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2002 'Please clean the distro tree or change directory path.'
2004 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2006 # Start to mount the ISO.
2007 action 'Mounting ISO image...'
2008 mkdir -p "$TMP_DIR"
2009 # Get ISO file size.
2010 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2011 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2012 sleep 2
2013 # Prepare target dir, copy the kernel and the rootfs.
2014 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2015 status
2017 action 'Copying the Linux kernel...'
2018 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2019 make_bzImage_hardlink "$TARGET/rootcd/boot"
2020 else
2021 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2022 fi
2023 status
2025 for i in $(ls $TMP_DIR); do
2026 [ "$i" == 'boot' ] && continue
2027 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2028 done
2030 for loader in isolinux syslinux extlinux grub; do
2031 [ -d "$TMP_DIR/boot/$loader" ] || continue
2032 action 'Copying %s files...' "$loader"
2033 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2034 status
2035 done
2037 action 'Copying the rootfs...'
2038 cp $TMP_DIR/boot/rootfs*.?z "$TARGET/rootcd/boot"
2039 status
2041 # Extract initramfs.
2042 cd "$TARGET/rootfs"
2043 action 'Extracting the rootfs...'
2044 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
2045 # unpack /usr
2046 for i in etc/tazlito/*.extract; do
2047 [ -f "$i" ] && . $i ../rootcd
2048 done
2049 # Umount and remove temp directory and cd to $TARGET to get stats.
2050 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2051 cd ..
2052 status
2054 newline
2055 separator
2056 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2057 echo "Distro tree : $(pwd)"
2058 echo "Rootfs size : $(du -sh rootfs)"
2059 echo "Rootcd size : $(du -sh rootcd)"
2060 footer
2061 ;;
2064 list-flavors)
2065 # Show available flavors.
2066 list='/etc/tazlito/flavors.list'
2067 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2068 title 'List of flavors'
2069 cat $list
2070 footer
2071 ;;
2074 show-flavor)
2075 # Show flavor descriptions.
2076 set -e
2077 flavor=${2%.flavor}
2078 flv_dir="$(extract_flavor "$flavor")"
2079 desc="$flv_dir/$flavor.desc"
2080 if [ -n "$brief" ]; then
2081 if [ -z "$noheader" ]; then
2082 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2083 separator
2084 fi
2085 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2086 "$(field ISO "$desc")" \
2087 "$(field Rootfs "$desc")" \
2088 "$(field Description "$desc")"
2089 else
2090 separator
2091 cat "$desc"
2092 fi
2093 cleanup
2094 ;;
2097 gen-liveflavor)
2098 # Generate a new flavor from the live system.
2099 FLAVOR=${2%.flavor}
2100 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2102 case "$FLAVOR" in
2103 -?|-h*|--help)
2104 cat <<EOT
2105 SliTaz Live Tool - Version: $VERSION
2107 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2109 $(boldify '<flavor-patch-file> format:')
2110 $(optlist "\
2111 code data
2112 + package to add
2113 - package to remove
2114 ! non-free package to add
2115 ? display message
2116 @ flavor description
2117 ")
2119 $(boldify 'Example:')
2120 $(optlist "\
2121 @ Developer tools for SliTaz maintainers
2122 + slitaz-toolchain
2123 + mercurial
2124 ")
2125 EOT
2126 exit 1
2127 ;;
2128 esac
2129 mv /etc/tazlito/distro-packages.list \
2130 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2131 rm -f distro-packages.list non-free.list 2>/dev/null
2132 tazpkg recharge
2134 DESC=""
2135 [ -n "$3" ] && \
2136 while read action pkg; do
2137 case "$action" in
2138 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2139 -) yes | tazpkg remove $pkg ;;
2140 !) echo $pkg >> non-free.list ;;
2141 @) DESC="$pkg" ;;
2142 \?) echo -en "$pkg"; read action ;;
2143 esac
2144 done < $3
2146 yes '' | tazlito gen-distro
2147 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2148 mv /etc/tazlito/distro-packages.list.$$ \
2149 /etc/tazlito/distro-packages.list 2>/dev/null
2150 ;;
2153 gen-flavor)
2154 # Generate a new flavor from the last ISO image generated
2155 FLAVOR=${2%.flavor}
2156 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2158 title 'Flavor generation'
2159 check_rootfs
2160 FILES="$FLAVOR.pkglist"
2162 action 'Creating file %s...' "$FLAVOR.flavor"
2163 for i in rootcd rootfs; do
2164 if [ -d "$ADDFILES/$i" ] ; then
2165 FILES="$FILES\n$FLAVOR.$i"
2166 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2167 fi
2168 done
2169 status
2171 answer=$(grep -s ^Description $FLAVOR.desc)
2172 answer=${answer#Description : }
2173 if [ -z "$answer" ]; then
2174 echo -n "Description: "
2175 read answer
2176 fi
2178 action 'Compressing flavor %s...' "$FLAVOR"
2179 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2180 echo "Description : $answer" >> $FLAVOR.desc
2181 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2182 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2183 for i in $(ls $ROOTFS$INSTALLED); do
2184 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2185 EXTRAVERSION=""
2186 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2187 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2188 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2189 echo "$i" >> $FLAVOR.nonfree
2190 else
2191 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2192 fi
2193 done
2194 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2195 for i in $LOCALSTATE/undigest/*/mirror ; do
2196 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2197 done
2198 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2199 touch -t 197001010100.00 $FLAVOR.*
2200 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2201 rm $(echo -e $FILES)
2202 status
2204 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2205 ;;
2208 upgrade-flavor)
2209 # Strip versions from pkglist and update estimated numbers in flavor.desc
2210 flavor="${2%.flavor}"
2211 set -e
2212 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2213 set +e
2215 flv_dir="$(extract_flavor "$flavor")"
2217 strip_versions "$flv_dir/$flavor.pkglist"
2219 action 'Updating %s...' "$flavor.desc"
2221 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2222 set -- $(module calc_sizes "$flv_dir" "$flavor")
2223 restore_mirrors >/dev/null
2225 sed -i -e '/Image is ready/d' \
2226 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2227 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2228 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2229 -e "s|\(Packages *:\).*$|\1 $4|" \
2230 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2231 "$flv_dir/$flavor.desc"
2233 pack_flavor "$flv_dir" "$flavor"
2234 status
2235 display_unknown "$flv_dir/err"
2236 display_warn "$flv_dir/warn"
2237 cleanup
2238 ;;
2241 extract-flavor)
2242 # Extract a flavor into $FLAVORS_REPOSITORY
2243 flavor="${2%.flavor}"
2244 set -e
2245 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2246 set +e
2248 action 'Extracting %s...' "$flavor.flavor"
2249 flv_dir="$(extract_flavor "$flavor" full)"
2250 storage="$FLAVORS_REPOSITORY/$flavor"
2252 rm -rf "$storage" 2>/dev/null
2253 mkdir -p "$storage"
2254 cp -a "$flv_dir"/* "$storage"
2255 rm "$storage/description"
2256 status
2258 strip_versions "$storage/packages.list"
2260 cleanup
2261 ;;
2264 pack-flavor)
2265 # Create a flavor from $FLAVORS_REPOSITORY.
2266 flavor=${2%.flavor}
2267 storage="$FLAVORS_REPOSITORY/$flavor"
2269 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2271 action 'Creating flavor %s...' "$flavor"
2272 tmp_dir="$(mktemp -d)"
2274 while read from to; do
2275 [ -s "$storage/$from" ] || continue
2276 cp -a "$storage/$from" "$tmp_dir/$to"
2277 done <<EOT
2278 mirrors $flavor.mirrors
2279 distro.sh $flavor-distro.sh
2280 receipt $flavor.receipt
2281 non-free.list $flavor.nonfree
2282 EOT
2284 # Build the package list.
2285 # It can include a list from another flavor with the keyword @include
2286 if [ -s "$storage/packages.list" ]; then
2287 include=$(grep '^@include' "$storage/packages.list")
2288 if [ -n "$include" ]; then
2289 include=${include#@include }
2290 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2291 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2292 else
2293 echo -e "\nERROR: Can't find include package list from $include\n"
2294 fi
2295 fi
2296 # Generate the final/initial package list
2297 [ -s "$storage/packages.list" ] && \
2298 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2299 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2300 fi
2302 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2303 # Process multi-rootfs flavor
2304 . "$storage/receipt"
2305 set -- $ROOTFS_SELECTION
2306 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2307 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2308 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2310 for i in rootcd rootfs; do
2311 mkdir "$tmp_dir/$i"
2312 # Copy extra files from the first flavor
2313 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2314 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2315 # Overload extra files by meta flavor
2316 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2317 [ -n "$(ls $tmp_dir/$i)" ] &&
2318 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2319 dogzip "$tmp_dir/$flavor.$i"
2320 rm -rf "$tmp_dir/$i"
2321 done
2322 else
2323 # Process plain flavor
2324 for i in rootcd rootfs; do
2325 [ -d "$storage/$i" ] || continue
2326 (cd "$storage/$i";
2327 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2328 done
2329 fi
2331 unset VERSION MAINTAINER ROOTFS_SELECTION
2332 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2333 ROOTFS_SIZE="$1 (estimated)"
2334 INITRAMFS_SIZE="$2 (estimated)"
2335 ISO_SIZE="$3 (estimated)"
2336 PKGNUM="$4"
2337 . "$storage/receipt"
2339 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2340 Flavor : $FLAVOR
2341 Description : $SHORT_DESC
2342 Version : $VERSION
2343 Maintainer : $MAINTAINER
2344 LiveCD RAM size : $FRUGAL_RAM
2345 Rootfs list : $ROOTFS_SELECTION
2346 Build date : $(date '+%Y%m%d at %T')
2347 Packages : $PKGNUM
2348 Rootfs size : $ROOTFS_SIZE
2349 Initramfs size : $INITRAMFS_SIZE
2350 ISO image size : $ISO_SIZE
2351 ================================================================================
2353 EOT
2355 rm -f $tmp_dir/packages.list
2356 pack_flavor "$tmp_dir" "$flavor"
2357 status
2358 display_unknown "$tmp_dir/err"
2359 display_warn "$flv_dir/warn"
2360 cleanup
2361 ;;
2364 get-flavor)
2365 # Get a flavor's files and prepare for gen-distro.
2366 flavor=${2%.flavor}
2367 title 'Preparing %s distro flavor' "$flavor"
2368 set -e
2369 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2370 set +e
2372 action 'Cleaning %s...' "$DISTRO"
2373 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2374 # Clean old files
2375 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2376 [ -f "$i" ] && rm "$i"
2377 done
2378 mkdir -p "$DISTRO"
2379 status
2381 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2383 action 'Extracting flavor %s...' "$flavor.flavor"
2384 flv_dir="$(extract_flavor "$flavor" info)"
2385 cp -a "$flv_dir"/* .
2386 mv packages.list distro-packages.list
2387 mv -f info /etc/tazlito
2388 status
2390 for i in rootcd rootfs; do
2391 if [ -d "$i" ]; then
2392 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2393 fi
2394 done
2396 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2397 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2399 action 'Updating %s...' 'tazlito.conf'
2400 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2401 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2402 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2403 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2404 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2405 status
2407 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2408 cleanup
2409 ;;
2412 iso2flavor)
2413 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2414 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2416 FLAVOR=${3%.flavor}
2417 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2418 mount -o loop,ro $2 $TMP_DIR/iso
2419 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2420 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2421 ! -s $TMP_DIR/flavor/*.desc ]; then
2422 _ 'META flavors are not supported.'
2423 umount -d $TMP_DIR/iso
2424 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2425 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2426 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2427 umount -d $TMP_DIR/iso
2428 else
2429 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2430 uncompress $i | \
2431 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2432 done
2433 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2434 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2435 '/etc/slitaz-release' '/boot/rootfs.gz'
2436 umount -d $TMP_DIR/iso
2437 else
2438 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2439 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2440 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2441 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2442 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2443 umount -d $TMP_DIR/iso
2444 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2445 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2446 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2447 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2448 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2449 < $TMP_DIR/rootfs$INSTALLED.md5
2450 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2451 if [ -s $TMP_DIR/flavor/*desc ]; then
2452 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2453 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2454 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2455 for i in rootfs rootcd ; do
2456 [ -s $TMP_DIR/flavor/*.list$i ] &&
2457 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2458 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2459 done
2460 else
2461 find_flavor_rootfs $TMP_DIR/rootfs
2462 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2463 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2464 for i in rootfs rootcd ; do
2465 [ "$(ls $TMP_DIR/$i)" ] &&
2466 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2467 done
2468 unset VERSION MAINTAINER
2469 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2470 if [ -n "$DESCRIPTION" ]; then
2471 _n 'Flavor version : '; read -t 30 VERSION
2472 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2473 fi
2475 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2476 Flavor : $FLAVOR
2477 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2478 Version : ${VERSION:-1.0}
2479 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2480 LiveCD RAM size : $RAM_SIZE
2481 Build date : $BUILD_DATE
2482 Packages : $PKGCNT
2483 Rootfs size : $ROOTFS_SIZE
2484 Initramfs size : $INITRAMFS_SIZE
2485 ISO image size : $ISO_SIZE
2486 ================================================================================
2488 EOT
2489 longline "Tazlito can't detect each file installed during \
2490 a package post_install. You should extract this flavor (tazlito extract-flavor \
2491 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2492 tree and remove files generated by post_installs.
2493 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2494 repack the flavor (tazlito pack-flavor $FLAVOR)"
2495 fi
2496 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2497 fi
2498 fi
2499 rm -rf $TMP_DIR
2500 ;;
2503 gen-distro)
2504 # Generate a live distro tree with a set of packages.
2506 check_root
2507 start_time=$(date +%s)
2509 # Tazlito options: --iso or --cdrom
2510 CDROM=''
2511 [ -n "$iso" ] && CDROM="-o loop $iso"
2512 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2514 # Check if a package list was specified on cmdline.
2515 if [ -f "$2" ]; then
2516 LIST_NAME="$2"
2517 else
2518 LIST_NAME='distro-packages.list'
2519 fi
2521 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2522 'Please clean the distro tree or change directory path.'
2523 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2524 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2526 # If list not given: build list with all installed packages
2527 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2528 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2529 fi
2531 # Exit if no list name.
2532 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2534 # Start generation.
2535 title 'Tazlito generating a distro'
2537 # Misc checks
2538 mkdir -p "$PACKAGES_REPOSITORY"
2539 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2540 newline
2542 # Mount CD-ROM to be able to repack boot-loader packages
2543 if [ ! -e /boot -a -n "$CDROM" ]; then
2544 mkdir $TMP_MNT
2545 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2546 ln -s "$TMP_MNT/boot" /
2547 if [ ! -d "$ADDFILES/rootcd" ] ; then
2548 mkdir -p "$ADDFILES/rootcd"
2549 for i in $(ls $TMP_MNT); do
2550 [ "$i" == 'boot' ] && continue
2551 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2552 done
2553 fi
2554 else
2555 rmdir "$TMP_MNT"
2556 fi
2557 fi
2559 # Rootfs stuff.
2560 echo 'Preparing the rootfs directory...'
2561 mkdir -p "$ROOTFS"
2562 export root="$ROOTFS"
2563 # pass current 'mirror' to the root
2564 mkdir -p $root/var/lib/tazpkg $root/etc
2565 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2566 cp -f /etc/slitaz-release $root/etc/slitaz-release
2567 strip_versions "$LIST_NAME"
2569 if [ "$REPACK" == 'y' ]; then
2570 # Determine full packages list with all dependencies
2571 tmp_dir="$(mktemp -d)"
2572 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2573 touch "$tmp_dir/full.pkglist"
2574 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2576 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2577 while read pkgname pkgver; do
2578 # Is package in full list?
2579 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2580 # Is package already repacked?
2581 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2582 _ 'Repacking %s...' "$pkgname-$pkgver"
2583 tazpkg repack "$pkgname" --quiet
2584 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2585 status
2586 done
2588 rm -r "$tmp_dir"
2589 fi
2591 if [ -f non-free.list ]; then
2592 # FIXME: working in the ROOTFS chroot?
2593 newline
2594 echo 'Preparing non-free packages...'
2595 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2596 for pkg in $(cat 'non-free.list'); do
2597 if [ ! -d "$INSTALLED/$pkg" ]; then
2598 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2599 tazpkg get-install get-$pkg
2600 fi
2601 get-$pkg "$ROOTFS"
2602 fi
2603 tazpkg repack $pkg
2604 pkg=$(ls $pkg*.tazpkg)
2605 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2606 mv $pkg $PACKAGES_REPOSITORY
2607 done
2608 fi
2609 cp $LIST_NAME $DISTRO/distro-packages.list
2610 newline
2612 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2614 cd $DISTRO
2615 cp distro-packages.list $ROOTFS/etc/tazlito
2616 # Copy all files from $ADDFILES/rootfs to the rootfs.
2617 if [ -d "$ADDFILES/rootfs" ] ; then
2618 action 'Copying addfiles content to the rootfs...'
2619 cp -a $ADDFILES/rootfs/* $ROOTFS
2620 status
2621 fi
2623 action 'Root filesystem is generated...'; status
2625 # Root CD part.
2626 action 'Preparing the rootcd directory...'
2627 mkdir -p $ROOTCD
2628 status
2630 # Move the boot dir with the Linux kernel from rootfs.
2631 # The efi & boot dirs go directly on the CD.
2632 if [ -d "$ROOTFS/efi" ] ; then
2633 action 'Moving the efi directory...'
2634 mv $ROOTFS/efi $ROOTCD
2635 status
2636 fi
2637 if [ -d "$ROOTFS/boot" ] ; then
2638 action 'Moving the boot directory...'
2639 mv $ROOTFS/boot $ROOTCD
2640 status
2641 fi
2642 cd $DISTRO
2643 # Copy all files from $ADDFILES/rootcd to the rootcd.
2644 if [ -d "$ADDFILES/rootcd" ] ; then
2645 action 'Copying addfiles content to the rootcd...'
2646 cp -a $ADDFILES/rootcd/* $ROOTCD
2647 status
2648 fi
2649 # Execute the distro script used to perform tasks in the rootfs
2650 # before compression. Give rootfs path in arg
2651 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2652 if [ -x "$DISTRO_SCRIPT" ]; then
2653 echo 'Executing distro script...'
2654 sh $DISTRO_SCRIPT $DISTRO
2655 fi
2657 # Execute the custom_rules() found in receipt.
2658 if [ -s "$TOP_DIR/receipt" ]; then
2659 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2660 echo -e "Executing: custom_rules()\n"
2661 . "$TOP_DIR/receipt"
2662 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2663 fi
2664 fi
2666 # Multi-rootfs
2667 if [ -s /etc/tazlito/rootfs.list ]; then
2669 FLAVOR_LIST="$(awk '{
2670 for (i = 2; i <= NF; i+=2)
2671 printf "%s ", $i;
2672 }' /etc/tazlito/rootfs.list)"
2674 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2675 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2676 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2678 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2679 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2680 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2681 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2683 n=0
2684 last=$ROOTFS
2685 while read flavor; do
2686 n=$(($n+1))
2687 mkdir ${ROOTFS}0$n
2688 export root="${ROOTFS}0$n"
2689 # initial tazpkg setup in empty rootfs
2690 tazpkg --root=$root >/dev/null 2>&1
2692 newline
2693 boldify "Building $flavor rootfs..."
2695 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2696 cp "$TOP_DIR/$flavor.flavor" .
2698 if [ ! -s "$flavor.flavor" ]; then
2699 # We may have it in $FLAVORS_REPOSITORY
2700 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2701 tazlito pack-flavor $flavor
2702 else
2703 download $flavor.flavor
2704 fi
2705 fi
2707 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2708 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2709 cp $flavor.pkglist $DISTRO/list-packages0$n
2710 status
2712 strip_versions "$DISTRO/list-packages0$n"
2714 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2716 action 'Updating the boot directory...'
2717 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2718 rm -rf ${ROOTFS}0$n/boot
2720 cd $DISTRO
2721 if [ -s $flavor.rootfs ]; then
2722 _n 'Adding %s rootfs extra files...' "$flavor"
2723 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2724 fi
2726 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2727 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2728 status
2730 rm -f $flavor.flavor install-list
2731 mergefs ${ROOTFS}0$n $last
2732 last=${ROOTFS}0$n
2733 done <<EOT
2734 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2735 EOT
2736 #'
2737 i=$(($n+1))
2738 while [ $n -gt 0 ]; do
2739 mv ${ROOTFS}0$n ${ROOTFS}$i
2740 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2741 gen_initramfs ${ROOTFS}$i
2742 n=$(($n-1))
2743 i=$(($i-1))
2744 export LZMA_HISTORY_BITS=26
2745 done
2746 mv $ROOTFS ${ROOTFS}$i
2747 gen_initramfs ${ROOTFS}$i
2748 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2749 ROOTFS=${ROOTFS}1
2750 else
2751 # Initramfs and ISO image stuff.
2752 gen_initramfs $ROOTFS
2753 fi
2754 gen_livecd_isolinux
2755 distro_stats
2756 cleanup
2757 ;;
2760 clean-distro)
2761 # Remove old distro tree.
2763 check_root
2764 title 'Cleaning: %s' "$DISTRO"
2765 if [ -d "$DISTRO" ] ; then
2766 if [ -d "$ROOTFS" ] ; then
2767 action 'Removing the rootfs...'
2768 rm -f $DISTRO/$INITRAMFS
2769 rm -rf $ROOTFS
2770 status
2771 fi
2772 if [ -d "$ROOTCD" ] ; then
2773 action 'Removing the rootcd...'
2774 rm -rf $ROOTCD
2775 status
2776 fi
2777 action 'Removing eventual ISO image...'
2778 rm -f $DISTRO/$ISO_NAME.iso
2779 rm -f $DISTRO/$ISO_NAME.md5
2780 status
2781 fi
2782 footer
2783 ;;
2786 check-distro)
2787 # Check for a few LiveCD needed files not installed by packages.
2789 # TODO: Remove this function.
2790 # First two files are maintained by tazpkg while it runs on rootfs,
2791 # while last one file should be maintained by tazlito itself.
2792 check_rootfs
2793 title 'Checking distro: %s' "$ROOTFS"
2794 # SliTaz release info.
2795 rel='/etc/slitaz-release'
2796 if [ ! -f "$ROOTFS$rel" ]; then
2797 _ 'Missing release info: %s' "$rel"
2798 else
2799 action 'Release : %s' "$(cat $ROOTFS$rel)"
2800 status
2801 fi
2802 # Tazpkg mirror.
2803 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2804 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2805 todomsg
2806 else
2807 action 'Mirror configuration exists...'
2808 status
2809 fi
2810 # Isolinux msg
2811 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2812 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2813 todomsg
2814 else
2815 action 'Isolinux message seems good...'
2816 status
2817 fi
2818 footer
2819 ;;
2822 writeiso)
2823 # Writefs to ISO image including /home unlike gen-distro we don't use
2824 # packages to generate a rootfs, we build a compressed rootfs with all
2825 # the current filesystem similar to 'tazusb writefs'.
2827 DISTRO='/home/slitaz/distro'
2828 ROOTCD="$DISTRO/rootcd"
2829 COMPRESSION="${2:-none}"
2830 ISO_NAME="${3:-slitaz}"
2831 check_root
2832 # Start info
2833 title 'Write filesystem to ISO'
2834 longline "The command writeiso will write the current filesystem into a \
2835 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2836 newline
2837 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2839 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2840 # Save some space
2841 rm -rf /var/cache/tazpkg/*
2842 rm -f /var/lib/tazpkg/*.bak
2843 rm -rf $DISTRO
2845 # Optionally remove sound card selection and screen resolution.
2846 if [ -z $LaunchedByTazpanel ]; then
2847 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2848 case $anser in
2849 y)
2850 action 'Removing current sound card and screen configurations...'
2851 rm -f /var/lib/sound-card-driver
2852 rm -f /var/lib/alsa/asound.state
2853 rm -f /etc/X11/xorg.conf ;;
2854 *)
2855 action 'Keeping current sound card and screen configurations...' ;;
2856 esac
2857 status
2858 newline
2860 # Optionally remove i18n settings
2861 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2862 case $anser in
2863 y)
2864 action 'Removing current locale/keymap settings...'
2865 newline > /etc/locale.conf
2866 newline > /etc/keymap.conf ;;
2867 *)
2868 action 'Keeping current locale/keymap settings...' ;;
2869 esac
2870 status
2871 fi
2873 # Clean-up files by default
2874 newline > /etc/udev/rules.d/70-persistent-net.rules
2875 newline > /etc/udev/rules.d/70-persistant-cd.rules
2877 # Create list of files including default user files since it is defined in /etc/passwd
2878 # and some new users might have been added.
2879 cd /
2880 echo 'init' > /tmp/list
2881 for dir in bin etc sbin var dev lib root usr home opt; do
2882 [ -d $dir ] && find $dir
2883 done >> /tmp/list
2885 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2886 [ -d $dir ] && echo $dir
2887 done >> /tmp/list
2889 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2891 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2892 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2893 #fi
2894 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2895 touch /var/log/wtmp
2897 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2898 sed -i "/var\/log\/$removelog/d" /tmp/list
2899 done
2901 # Generate initramfs with specified compression and display rootfs
2902 # size in realtime.
2903 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2905 write_initramfs &
2906 sleep 2
2907 cd - > /dev/null
2908 echo -en "\nFilesystem size:"
2909 while [ ! -f /tmp/rootfs ]; do
2910 sleep 1
2911 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2912 done
2913 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2914 echo -e "\n"
2915 rm -f /tmp/rootfs
2917 # Move freshly generated rootfs to the cdrom.
2918 mkdir -p $ROOTCD/boot
2919 mv -f /$INITRAMFS $ROOTCD/boot
2920 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2922 # Now we need the kernel and isolinux files.
2923 copy_from_cd() {
2924 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2925 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2926 unmeta_boot $ROOTCD
2927 umount /media/cdrom
2930 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2931 copy_from_cd;
2932 elif mount | grep /media/cdrom; then
2933 copy_from_cd;
2934 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2935 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2936 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2937 else
2938 touch /tmp/.write-iso-error
2939 longline "When SliTaz is running in RAM the kernel and bootloader \
2940 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2941 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2942 echo -en "----\nENTER to continue..."; read i
2943 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2944 copy_from_cd
2945 fi
2947 # Generate the iso image.
2948 touch /tmp/.write-iso
2949 newline
2950 cd $DISTRO
2951 create_iso $ISO_NAME.iso $ROOTCD
2952 action 'Creating the ISO md5sum...'
2953 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2954 status
2956 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2957 rm -f /tmp/.write-iso
2959 if [ -z $LaunchedByTazpanel ]; then
2960 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2961 case $anser in
2962 y)
2963 umount /dev/cdrom 2>/dev/null
2964 eject
2965 echo -n "Please insert a blank CD-ROM and press ENTER..."
2966 read i && sleep 2
2967 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2968 echo -en "----\nENTER to continue..."; read i ;;
2969 *)
2970 exit 0 ;;
2971 esac
2972 fi
2973 ;;
2976 burn-iso)
2977 # Guess CD-ROM device, ask user and burn the ISO.
2979 check_root
2980 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2981 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2982 # We can specify an alternative ISO from the cmdline.
2983 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2984 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2986 title 'Tazlito burn ISO'
2987 echo "CD-ROM device : /dev/$DRIVE_NAME"
2988 echo "Drive speed : $DRIVE_SPEED"
2989 echo "ISO image : $iso"
2990 footer
2992 case $(yesorno 'Burn ISO image?' 'n') in
2993 y)
2994 title 'Starting Wodim to burn the ISO...'
2995 sleep 2
2996 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2997 footer 'ISO image is burned to CD-ROM.'
2998 ;;
2999 *)
3000 die 'Exiting. No ISO burned.'
3001 ;;
3002 esac
3003 ;;
3006 merge)
3007 # Merge multiple rootfs into one iso.
3009 if [ -z "$2" ]; then
3010 cat <<EOT
3011 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3013 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3014 i.e: rootfsN is a subset of rootfsN-1
3015 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3016 The boot loader will select the rootfs according to the RAM size detected.
3018 Example:
3019 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3021 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3022 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3024 EOT
3025 exit 2
3026 fi
3028 shift # skip merge
3029 append="$1 slitaz1"
3030 shift # skip size1
3031 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3033 ISO=$1.merged
3035 # Extract filesystems
3036 action 'Mounting %s' "$1"
3037 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3038 status || cleanup_merge
3040 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3041 make_bzImage_hardlink $TMP_DIR/iso/boot
3042 umount -d $TMP_DIR/mnt
3043 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3044 _ '%s is already a merged iso. Aborting.' "$1"
3045 cleanup_merge
3046 fi
3047 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3048 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3049 if [ ! -f /boot/isolinux/ifmem.c32 -a
3050 ! -f /boot/isolinux/c32box.c32 ]; then
3051 cat <<EOT
3052 No file /boot/isolinux/ifmem.c32
3053 Please install syslinux package !
3054 EOT
3055 rm -rf $TMP_DIR
3056 exit 1
3057 fi
3058 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3059 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3060 fi
3062 action 'Extracting %s' 'iso/rootfs.gz'
3063 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3064 [ -d $TMP_DIR/rootfs1/etc ]
3065 status || cleanup_merge
3067 n=1
3068 while [ -n "$2" ]; do
3069 shift # skip rootfs N-1
3070 p=$n
3071 n=$(($n + 1))
3072 append="$append $1 slitaz$n"
3073 shift # skip size N
3074 mkdir -p $TMP_DIR/rootfs$n
3076 action 'Extracting %s' "$1"
3077 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3078 [ -d "$TMP_DIR/rootfs$n/etc" ]
3079 status || cleanup_merge
3081 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3082 action 'Creating %s' "rootfs$p.gz"
3083 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3084 status
3085 done
3086 action 'Creating %s' "rootfs$n.gz"
3087 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3088 status
3089 rm -f $TMP_DIR/iso/boot/rootfs.gz
3090 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3091 create_iso $ISO $TMP_DIR/iso
3092 rm -rf $TMP_DIR
3093 ;;
3096 repack)
3097 # Repack an iso with maximum lzma compression ratio.
3099 ISO=$2
3100 mkdir -p $TMP_DIR/mnt
3102 # Extract filesystems
3103 action 'Mounting %s' "$ISO"
3104 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3105 status || cleanup_merge
3107 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3108 umount -d $TMP_DIR/mnt
3110 for i in $TMP_DIR/iso/boot/rootfs* ; do
3111 action 'Repacking %s' "$(basename $i)"
3112 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3113 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3114 align_to_32bits $i
3115 status
3116 done
3118 create_iso $ISO $TMP_DIR/iso
3119 rm -rf $TMP_DIR
3120 ;;
3123 build-loram)
3124 # Build a Live CD for low RAM systems.
3126 ISO="$2"
3127 OUTPUT="$3"
3128 [ -z "$3" ] && \
3129 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3130 mkdir -p "$TMP_DIR/iso"
3131 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3132 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3133 if ! check_iso_for_loram ; then
3134 umount -d "$TMP_DIR/iso"
3135 die "$ISO is not a valid SliTaz live CD. Abort."
3136 fi
3137 case "$4" in
3138 cdrom) build_loram_cdrom ;;
3139 http) build_loram_http ;;
3140 *) build_loram_ram "$5" ;;
3141 esac
3142 umount $TMP_DIR/iso # no -d: needs /proc
3143 losetup -d $loopdev
3144 rm -rf $TMP_DIR
3145 ;;
3148 emu-iso)
3149 # Emulate an ISO image with Qemu.
3150 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3151 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3152 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3153 echo -e "\nStarting Qemu emulator:\n"
3154 echo -e "qemu $QEMU_OPTS $iso\n"
3155 qemu $QEMU_OPTS $iso
3156 ;;
3159 deduplicate)
3160 # Deduplicate files in a tree
3161 shift
3162 deduplicate "$@"
3163 ;;
3166 usage|*)
3167 # Print usage also for all unknown commands.
3168 usage
3169 ;;
3170 esac
3172 exit 0