tazlito view tazlito @ rev 476

uefi support aventually...
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Jan 19 21:06:16 2018 +0100 (2018-01-19)
parents fb83501c662e
children 7959015b775d
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 for the /boot/isolinux/efi.img file
264 fix_efi_img_size() {
265 local e=$((0x809C))
266 for i in BOOT ISOLINUX EFI.IMG ; do
267 local sz=$(get $(($e+10)) "$2")
268 e=$(($(get $(($e+2)) "$2") * 2048))
269 while [ $sz -gt 0 ]; do
270 local len=$(get $e "$2" 2)
271 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
272 2>/dev/null)" == "$i" ] && continue 2
273 [ $len -eq 0 ] && break
274 sz=$(($sz-$len))
275 e=$(($e+$len))
276 done
277 return # not found
278 done
279 set64 $(($e+10)) $1 "$2"
280 }
283 # create /boot/isolinux/efi.img to share EFI files with the iso image
285 fixup_uefi_part() {
286 local n
287 [ -s $2/boot/isolinux/efi.img ] || return
289 # Build file list tree
291 ( cd $2 ; find efi -type f -exec echo \
292 'stat -c "$(stat -m {} | sed q) %s f %n" {}' \; | sh | sort -n ) \
293 >/tmp/fatfiles$$
294 n=$(sed 's/ .*//;q' /tmp/fatfiles$$)
295 ( cd $2; find efi ) | awk -v n=$n 'BEGIN { FS="/" }
296 NF > 1 {
297 d[NF $NF]+=2
298 p[NF $NF]=$0
299 b[a++]=NF $NF
300 if (NF>2) d[NF-1 $(NF-1)]++
301 }
302 END {
303 while (a-- > 0) if (d[i=b[a]] > 2) {
304 n-= j =int((d[i]+63)/64)
305 print n " " j*2048 " d " p[i]
306 }
307 print n-1 " 2048 d efi"
308 }' >>/tmp/fatfiles$$
309 sort -n /tmp/fatfiles$$ | awk '{ if (s == 0) s=$1;
310 print ($1-s)+2 " " $2 " " $3 " " $4 }' > /tmp/fatfiles$$.tmp
311 mv -f /tmp/fatfiles$$.tmp /tmp/fatfiles$$
313 # Build fat12 or fat16
315 if [ $(awk '{n+=int(($2+2047)/2048)}END{print n}' /tmp/fatfiles$$) \
316 -lt 4000 ]; then
317 sed '1s/.*/4087 2049 x\n1 1 x/' /tmp/fatfiles$$ | while read c s x; do
318 seq $(($c+1)) $((($s-1)/2048+$c))
319 echo 4095
320 done | awk 'BEGIN { printf "0 "}
321 {
322 if (n == 0) n=$1
323 else {
324 printf "%02X %02X %02X ",n%256,
325 ($1%16)*16+(n/256),$1/16
326 n=0
327 }
328 }
329 END {
330 if (n != 0) printf "FF 0F 00 "
331 print " |"
332 }' | hexdump -R > /tmp/fatbin-12-$$
333 else
334 sed '1s/.*/65527 2049 x\n1 1 x/' /tmp/fatfiles$$ | while read c s x; do
335 seq $(($c+1)) $((($s-1)/2048+$c))
336 echo 65535
337 done | awk 'BEGIN { printf "0 "}
338 {
339 printf "%02X %02X ",$1%256,$1/256
340 }
341 END {
342 print " |"
343 }' | hexdump -R > /tmp/fatbin-16-$$
344 fi
346 # align fat to 2k
347 dd of=$(ls /tmp/fatbin-*-$$) count=0 bs=2048 \
348 seek=$((($(stat -c %s /tmp/fatbin-*-$$)-1)/2048+1)) 2>/dev/null
350 # build directory records
352 awk '
353 BEGIN {
354 c=2
355 b16="/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0"
356 b14="/0/0/0/0/0/0/0/0/0/0/0/0/0/0"
357 print "EFI /x10" b14 "/x0" c "/0/0/x08/0/0"
358 for (n=i=0; i<63; i++) print b16 b16
359 }
360 {
361 clu[n]=$1
362 size[n]=$2
363 type[n]=$3
364 name[n]=$4
365 n++
366 }
367 END {
368 path="efi"
369 d21="/x10" b14 "/x%02X/x%02X/0/x08/0/0\n"
370 up[0]=0
371 s=1
372 do {
373 l=split(path,x,"/")
374 up[l]=c
375 printf ". " d21,c%256,c/256
376 printf ".. " d21,up[l-1]%256,up[l-1]/256
377 for (i=s,e=2; i<n; i++) {
378 if (substr(name[i],1,length(path)) != path ||
379 split(substr(name[i],length(path)+2),x,"/") > 1)
380 continue
381 split(toupper(x[1]),x,".")
382 if (length(x[1]) >= 8) printf substr(x[1],1,8)
383 else printf x[1] substr(" ",1,8-length(x[1]))
384 if (length(x[2]) >= 3) printf substr(x[2],1,3)
385 else printf x[2] substr(" ",1,3-length(x[2]))
386 if (type[i] == "d") printf "/x10"; else printf "/0"
387 printf b14 "/x%02X/x%02X",clu[i]%256,clu[i]/256
388 printf "/x%02X/x%02X/x%02X/x%02X\n",size[i]%256,
389 (size[i]/256)%256,(size[i]/256/256)%256,
390 size[i]/256/256/256
391 e++
392 }
393 while (e++ < 64) print b16 b16
394 path=name[s]
395 c=clu[s]
396 } while (type[s++] == "d")
397 }' < /tmp/fatfiles$$ | while read line; do
398 echo "$line" | sed 's| |/x20|g;s|/|\\\\|g' | xargs echo -en
399 done > /tmp/fatdir$$
401 # build boot record
403 fat=$(($(stat -c %s /tmp/fatbin-*-$$)/512))
404 r=$((4-($fat+$fat+$(stat -c %s /tmp/fatdir$$)/512)%4))
405 dd if=/dev/zero bs=512 count=$r of=/tmp/fatbr$$ 2> /dev/null
406 echo -en '\x55\xAA' | \
407 dd of=/tmp/fatbr$$ seek=510 bs=1 conv=notrunc 2> /dev/null
408 n=$(stat -m $2/boot/isolinux/efi.img | sed q)
409 fat="$(printf "%02X %02X" $(($fat%256)) $((($fat>>8)%256)))"
410 s=$((($(stat -m $(ls -r $2/boot/rootfs* | sed q) | sed q) - $n)*4))
411 if [ $s -gt 65535 ]; then
412 size="00 00"
413 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
414 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
415 else
416 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
417 size32="00 00 00 00"
418 fi
419 t=32; [ -s /tmp/fatbin-16-$$ ] && t=36
420 hexdump -R <<EOT | dd conv=notrunc of=/tmp/fatbr$$ 2> /dev/null
421 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $r 00 |
422 0 02 40 00 $size f8 $fat 20 00 40 00 00 00 00 00 |
423 0 $size32 80 00 29 00 00 00 00 4e 4f 20 4e 41 |
424 0 4d 45 20 20 20 20 46 41 54 31 $t 20 20 20 cd 18 |
425 0 cd 19 eb fa |
426 EOT
428 # patch efi.img stub
430 cat /tmp/fatbr$$ /tmp/fatbin-*-$$ /tmp/fatbin-*-$$ /tmp/fatdir$$ | \
431 dd of=$1 conv=notrunc bs=2k seek=$n 2>/dev/null
432 fix_efi_img_size $(($s*512)) $1
433 rm -f /tmp/fat*$$
434 }
437 # allocate efi.img stub to share EFI files in the EFI boot partition
439 alloc_uefi_part() {
440 local basedir=$(dirname "$1")/..
441 local clusters=$({
442 [ -d $basedir/efi ] &&
443 find $basedir/efi -type f -exec stat -c "%s" {} \;
444 while [ -s "$1" ]; do
445 local efifile
446 case "$1" in
447 *taz) efifile=bootia32.efi ;;
448 *taz64) efifile=bootx64.efi ;;
449 esac
450 if [ ! -s $basedir/efi/boot/$efifile ] &&
451 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
452 stat -c "%s" "$1"
453 mkdir -p $basedir/efi/boot 2> /dev/null
454 ln "$1" $basedir/efi/boot/$efifile
455 fi
456 shift
457 done; } | awk '{ n+=int(($1+2047)/2048) } END { print n }')
458 [ $clusters -eq 0 ] && return
459 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
460 BEGIN {
461 FS="/"
462 }
463 NF > 1 {
464 d[NF $NF]+=2
465 d[NF-1 $(NF-1)]++
466 }
467 END {
468 for (i in d)
469 n+=int((d[i]+63)/64)
470 print n
471 }')
472 clusters=$(($clusters+$dclust))
473 if [ $clusters -lt 4000 ]; then
474 # reserved + fat*2 + root dir + dirs
475 count=$(( 1 + (($clusters*3+4095)/4096)*2 + 1 + $dclust ))
476 else
477 # reserved + fat*2 + root dir + dirs
478 count=$(( 1 + (($clusters+1023)/1024)*2 + 1 + $dclust ))
479 fi
480 dd if=/dev/zero bs=2k of=$basedir/boot/isolinux/efi.img count=$count
481 }
484 # isolinux.conf doesn't know the kernel version.
485 # We name the kernel image 'bzImage'.
486 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
488 make_bzImage_hardlink() {
489 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
490 rm -f ${1:-.}/bzImage 2>/dev/null
491 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
492 fi
493 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
494 rm -f ${1:-.}/bzImage64 2> /dev/null
495 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
496 fi
497 }
500 create_iso() {
501 cd $2
502 deduplicate
504 make_bzImage_hardlink $2/boot
505 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
507 cat > /tmp/cdsort$$ <<EOT
508 $PWD/boot/isolinux 100
509 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
510 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
511 $(find $PWD/efi -type f 2>/dev/null | awk 'BEGIN{n=299} { print $1 " " n-- }')
512 $PWD/boot/isolinux/efi.img 300
513 $PWD/boot/isolinux/isolinux.bin 399
514 $PWD/boot/isolinux/boot.cat 400
515 EOT
517 action 'Computing md5...'
518 touch boot/isolinux/boot.cat
519 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
520 status
522 cd - >/dev/null
523 title 'Generating ISO image'
525 _ 'Generating %s' "$1"
526 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
527 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
528 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
529 -no-emul-boot -boot-load-size 4 -boot-info-table \
530 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
531 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
532 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
533 -A "tazlito $VERSION/$(genisoimage --version)" \
534 -copyright README -P "www.slitaz.org" -no-pad $2
535 rm -f /tmp/cdsort$$
536 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
538 mkdir /tmp/mnt$$
539 mount -o loop,ro $1 /tmp/mnt$$
540 fixup_uefi_part $1 /tmp/mnt$$
541 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
542 ${uefi:+boot/isolinux/efi.img} ; do
543 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
544 done
545 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
546 seek=$(stat -m /tmp/mnt$$/md5sum | sed q) 2> /dev/null
547 umount -d /tmp/mnt$$
548 rmdir /tmp/mnt$$
550 if [ -s '/etc/tazlito/info' ]; then
551 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
552 action 'Storing ISO info...'
553 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
554 status
555 fi
556 fi
558 if [ -x '/usr/bin/isohybrid' ]; then
559 action 'Creating hybrid ISO...'
560 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
561 status
562 fi
564 if [ -x '/usr/bin/iso2exe' ]; then
565 echo 'Creating EXE header...'
566 /usr/bin/iso2exe $1 2>/dev/null
567 fi
568 }
571 # Generate a new ISO image using isolinux.
573 gen_livecd_isolinux() {
574 # Some packages may want to alter iso
575 genisohooks iso
576 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
578 # Set date for boot msg.
579 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
580 DATE=$(date +%Y%m%d)
581 action 'Setting build date to: %s...' "$DATE"
582 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
583 status
584 fi
586 cd $DISTRO
587 create_iso $ISO_NAME.iso $ROOTCD
589 action 'Creating the ISO md5sum...'
590 md5sum $ISO_NAME.iso > $ISO_NAME.md5
591 status
593 separator
594 # Some packages may want to alter final iso
595 genisohooks final
596 }
599 lzma_history_bits() {
600 #
601 # This generates an ISO which boots with Qemu but gives
602 # rootfs errors in frugal or liveUSB mode.
603 #
604 # local n
605 # local sz
606 # n=20 # 1Mb
607 # sz=$(du -sk $1 | cut -f1)
608 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
609 # n=$(( $n + 1 ))
610 # sz=$(( $sz / 2 ))
611 # done
612 # echo $n
613 echo ${LZMA_HISTORY_BITS:-24}
614 }
617 lzma_switches() {
618 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
619 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
620 }
623 lzma_set_size() {
624 # Update size field for lzma'd file packed using -si switch
625 return # Need to fix kernel code?
627 local n i
628 n=$(unlzma < $1 | wc -c)
629 for i in $(seq 1 8); do
630 printf '\\\\x%02X' $(($n & 255))
631 n=$(($n >> 8))
632 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
633 }
636 align_to_32bits() {
637 local size=$(stat -c %s ${1:-/dev/null})
638 [ $((${size:-0} & 3)) -ne 0 ] &&
639 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
640 }
643 dogzip() {
644 gzip -9 > $1
645 [ -x /usr/bin/advdef ] && advdef -qz4 $1
646 }
649 # Pack rootfs
651 pack_rootfs() {
652 ( cd $1; find . -print | cpio -o -H newc ) | \
653 case "$COMPRESSION" in
654 none)
655 _ 'Creating %s without compression...' 'initramfs'
656 cat > $2
657 ;;
658 gzip)
659 _ 'Creating %s with gzip compression...' 'initramfs'
660 dogzip $2
661 ;;
662 *)
663 _ 'Creating %s with lzma compression...' 'initramfs'
664 lzma e -si -so $(lzma_switches $1) > $2
665 lzma_set_size $2
666 ;;
667 esac
668 align_to_32bits $2
669 echo 1 > /tmp/rootfs
670 }
673 # Compression functions for writeiso.
675 write_initramfs() {
676 case "$COMPRESSION" in
677 lzma)
678 _n 'Creating %s with lzma compression...' "$INITRAMFS"
679 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
680 align='y'
681 lzma_set_size "/$INITRAMFS"
682 ;;
683 gzip)
684 _ 'Creating %s with gzip compression...' "$INITRAMFS"
685 cpio -o -H newc | dogzip "/$INITRAMFS"
686 ;;
687 *)
688 # align='y'
689 _ 'Creating %s without compression...' "$INITRAMFS"
690 cpio -o -H newc > "/$INITRAMFS"
691 ;;
692 esac < /tmp/list
693 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
694 echo 1 > /tmp/rootfs
695 }
698 # Deduplicate files (MUST be on the same filesystem).
700 deduplicate() {
701 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
702 (
703 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
704 while read attr inode link file; do
705 [ -L "$file" ] && continue
706 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
707 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
708 rm -f "$file"
709 if ln "$old_file" "$file" 2>/dev/null; then
710 inode="$old_inode"
711 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
712 save="$(($save+(${attr%%-*}+512)/1024))"
713 else
714 cp -a "$old_file" "$file"
715 fi
716 fi
717 fi
718 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
719 done
720 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
721 )
723 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
724 (
725 old_attr=""; hardlinks=0;
726 while read attr inode link file; do
727 attr="${attr/-TARGET-/-$(readlink $file)}"
728 if [ "$attr" == "$old_attr" ]; then
729 if [ "$inode" != "$old_inode" ]; then
730 rm -f "$file"
731 if ln "$old_file" "$file" 2>/dev/null; then
732 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
733 else
734 cp -a "$old_file" "$file"
735 fi
736 fi
737 else
738 old_file="$file"
739 old_attr="$attr"
740 old_inode="$inode"
741 fi
742 done
743 _ '%s duplicate symlinks.' "$hardlinks"
744 )
745 }
748 # Generate a new initramfs from the root filesystem.
750 gen_initramfs() {
751 # Just in case CTRL+c
752 rm -f $DISTRO/gen
754 # Some packages may want to alter rootfs
755 genisohooks rootfs
756 cd $1
758 # Normalize file time
759 find $1 -newer $1 -exec touch -hr $1 {} \;
761 # Link duplicate files
762 deduplicate
764 # Use lzma if installed. Display rootfs size in realtime.
765 rm -f /tmp/rootfs 2>/dev/null
766 pack_rootfs . $DISTRO/$(basename $1).gz &
767 sleep 2
768 echo -en "\nFilesystem size:"
769 while [ ! -f /tmp/rootfs ]; do
770 sleep 1
771 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
772 done
773 echo -e "\n"
774 rm -f /tmp/rootfs
775 cd $DISTRO
776 mv $(basename $1).gz $ROOTCD/boot
777 }
780 distro_sizes() {
781 if [ -n "$start_time" ]; then
782 time=$(($(date +%s) - $start_time))
783 sec=$time
784 div=$(( ($time + 30) / 60))
785 [ "$div" -ne 0 ] && min="~ ${div}m"
786 _ 'Build time : %ss %s' "$sec" "$min"
787 fi
788 cat <<EOT
789 Build date : $(date +%Y%m%d)
790 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
791 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
792 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
793 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
794 EOT
795 footer "Image is ready: $ISO_NAME.iso"
796 }
799 # Print ISO and rootfs size.
801 distro_stats() {
802 title 'Distro statistics: %s' "$DISTRO"
803 distro_sizes
804 }
807 # Create an empty configuration file.
809 empty_config_file() {
810 cat >> tazlito.conf <<"EOF"
811 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
812 #
814 # Name of the ISO image to generate.
815 ISO_NAME=""
817 # ISO image volume name.
818 VOLUM_NAME="SliTaz"
820 # Name of the preparer.
821 PREPARED="$USER"
823 # Path to the packages repository and the packages.list.
824 PACKAGES_REPOSITORY=""
826 # Path to the distro tree to gen-distro from a list of packages.
827 DISTRO=""
829 # Path to the directory containing additional files
830 # to copy into the rootfs and rootcd of the LiveCD.
831 ADDFILES="$DISTRO/addfiles"
833 # Default answer for binary question (Y or N)
834 DEFAULT_ANSWER="ASK"
836 # Compression utility (lzma, gzip or none)
837 COMPRESSION="lzma"
838 EOF
839 }
842 # Extract rootfs.gz somewhere
844 extract_rootfs() {
845 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
846 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
847 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
848 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
849 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
850 }
853 # Extract flavor file to temp directory
855 extract_flavor() {
856 # Input: $1 - flavor name to extract;
857 # $2 = absent/empty: just extract 'outer layer'
858 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
859 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
860 # Output: temp dir path where flavor was extracted
861 local f="$1.flavor" from to infos="$1.desc"
862 [ -f "$f" ] || die "File '$f' not found"
863 local dir="$(mktemp -d)"
864 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
866 if [ -n "$2" ]; then
867 cd $dir
869 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
871 for i in rootcd rootfs; do
872 [ -f "$1.$i" ] || continue
873 mkdir "$i"
874 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
875 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
876 rm "$1.$i"
877 done
878 touch -t 197001010100.00 "$1.*"
879 # Info to be stored inside ISO
880 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
881 rm $1.list*
883 # Renames
884 while read from to; do
885 [ -f "$from" ] || continue
886 mv "$from" "$to"
887 done <<EOT
888 $1.nonfree non-free.list
889 $1.pkglist packages.list
890 $1-distro.sh distro.sh
891 $1.receipt receipt
892 $1.mirrors mirrors
893 $1.desc description
894 EOT
895 fi
897 echo $dir
898 }
901 # Pack flavor file from temp directory
903 pack_flavor() {
904 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
905 }
908 # Remove duplicate files
910 files_match() {
911 if [ -d "$1" ]; then
912 return 1
914 elif [ -L "$1" ] && [ -L "$2" ]; then
915 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
917 elif [ -f "$1" ] && [ -f "$2" ]; then
918 cmp -s "$1" "$2" && return 0
920 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
921 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
922 return 0
924 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
925 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
926 return 0
928 fi
929 return 1
930 }
932 remove_with_path() {
933 dir="$(dirname $1)"
934 rm -f "$1"
935 while rmdir "$dir" 2> /dev/null; do
936 dir="$(dirname $dir)"
937 done
938 }
940 mergefs() {
941 # Note, many packages have files with spaces in the name
942 IFS=$'\n'
944 local size1=$(du -hs "$1" | awk '{ print $1 }')
945 local size2=$(du -hs "$2" | awk '{ print $1 }')
946 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
948 # merge symlinks files and devices
949 ( cd "$1"; find ) | \
950 while read file; do
951 files_match "$1/$file" "$2/$file" "$file" &&
952 remove_with_path "$2/$file"
953 done
955 unset IFS
956 status
957 }
960 cleanup_merge() {
961 rm -rf $TMP_DIR
962 exit 1
963 }
966 # Update isolinux config files for multiple rootfs
968 update_bootconfig() {
969 local files
970 action 'Updating boot config files...'
971 files="$(grep -l 'include common' $1/*.cfg)"
972 for file in $files; do
973 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
974 if (/label/) label=$0;
975 else if (/kernel/) kernel=$0;
976 else if (/append/) {
977 i=index($0,"rootfs.gz");
978 append=substr($0,i+9);
979 }
980 else if (/include/) {
981 for (i = 1; i <= n; i++) {
982 print label i
983 print kernel;
984 initrd="initrd=/boot/rootfs" n ".gz"
985 for (j = n - 1; j >= i; j--) {
986 initrd=initrd ",/boot/rootfs" j ".gz";
987 }
988 printf "\tappend %s%s\n",initrd,append;
989 print "";
990 }
991 print;
992 }
993 else print;
994 }' < $file > $file.$$
995 mv -f $file.$$ $file
996 done
997 sel="$(echo $2 | awk '{
998 for (i=1; i<=NF; i++)
999 if (i % 2 == 0) printf " slitaz%d", i/2
1000 else printf " %s", $i
1001 }')"
1003 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1005 label slitaz
1006 kernel /boot/isolinux/ifmem.c32
1007 append$sel noram
1009 label noram
1010 config noram.cfg
1012 EOT
1014 # Update vesamenu
1015 if [ -s "$1/isolinux.cfg" ]; then
1016 files="$files $1/isolinux.cfg"
1017 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1018 BEGIN {
1019 kernel = " COM32 c32box.c32"
1022 if (/ROWS/) print "MENU ROWS " n+$3;
1023 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1024 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1025 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1026 else if (/VSHIFT/) {
1027 x = $3-n;
1028 if (x < 0) x = 0;
1029 print "MENU VSHIFT " x;
1031 else if (/rootfs.gz/) {
1032 linux = "";
1033 if (/bzImage/) linux = "linux /boot/bzImage ";
1034 i = index($0, "rootfs.gz");
1035 append = substr($0, i+9);
1036 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1037 printf "\tappend%s noram\n", sel;
1038 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1039 for (i = 1; i <= n; i++) {
1040 print "LABEL slitaz" i
1041 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1042 printf "%s\n", kernel;
1043 initrd = "initrd=/boot/rootfs" n ".gz"
1044 for (j = n - 1; j >= i; j--) {
1045 initrd = initrd ",/boot/rootfs" j ".gz";
1047 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1050 else if (/bzImage/) kernel = $0;
1051 else print;
1052 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1053 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1054 fi
1056 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1057 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1058 cat > $1/noram.cfg <<EOT
1059 implicit 0
1060 prompt 1
1061 timeout 80
1062 $(grep '^F[0-9]' $1/isolinux.cfg)
1064 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1065 say Not enough RAM to boot slitaz. Trying hacker mode...
1066 default hacker
1067 label hacker
1068 KERNEL /boot/bzImage
1069 append rw root=/dev/null vga=normal
1071 label reboot
1072 EOT
1074 if [ -s $1/c32box.c32 ]; then
1075 cat >> $1/noram.cfg <<EOT
1076 COM32 c32box.c32
1077 append reboot
1079 label poweroff
1080 COM32 c32box.c32
1081 append poweroff
1083 EOT
1084 else
1085 echo " com32 reboot.c32" >> $1/noram.cfg
1086 fi
1088 # Restore real label names
1089 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1090 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1091 while read pat; do
1092 sed -i "s/slitaz$pat/" $files
1093 done
1094 status
1098 # Uncompress rootfs or module to stdout
1100 uncompress() {
1101 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1102 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1106 # Install a missing package
1108 install_package() {
1109 if [ -z "$2" ]; then
1110 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1111 else
1112 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1113 fi
1114 case "$answer" in
1115 y)
1116 # We don't want package on host cache.
1117 action 'Getting and installing package: %s' "$1"
1118 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1119 status ;;
1120 *)
1121 return 1 ;;
1122 esac
1126 # Check iso for loram transformation
1128 check_iso_for_loram() {
1129 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1130 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1134 # Build initial rootfs for loram ISO ram/cdrom/http
1136 build_initfs() {
1137 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1138 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1139 mirror3.slitaz.org mirror.slitaz.org"
1140 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1141 [ -z "$version" ] && die "Can't find the kernel version." \
1142 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1144 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1145 need_lib=false
1146 for i in bin dev run mnt proc tmp sys lib/modules; do
1147 mkdir -p $TMP_DIR/initfs/$i
1148 done
1149 ln -s bin $TMP_DIR/initfs/sbin
1150 ln -s . $TMP_DIR/initfs/usr
1151 for aufs in aufs overlayfs; do
1152 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1153 install_package $aufs $version && break
1154 done || return 1
1155 [ -s /init ] || install_package slitaz-boot-scripts
1156 cp /init $TMP_DIR/initfs/
1157 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1158 $TMP_DIR/initfs/lib/modules
1159 if [ "$1" == 'cdrom' ]; then
1160 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1161 else
1162 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1163 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1164 install_package linux-squashfs $version || return 1
1165 done
1166 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1167 $TMP_DIR/initfs/lib/modules
1168 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1169 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1170 fi
1171 if [ "$1" == 'http' ]; then
1172 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1173 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1174 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1175 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1176 cp -a /dev/fuse $TMP_DIR/initfs/dev
1177 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1178 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1179 else
1180 need_lib=true
1181 fi
1182 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1183 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1184 else
1185 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1186 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1187 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1188 cp -a /lib/librt* $TMP_DIR/initfs/lib
1189 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1190 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1191 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1192 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1193 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1194 need_lib=true
1195 fi
1196 cd $TMP_DIR/fs
1197 echo 'Getting slitaz-release & ethernet modules...'
1198 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1199 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1200 [ -s rootfs* ] || continue
1201 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1202 rm -f rootfs*
1203 done 2>&1 > /dev/null
1204 cd - > /dev/null
1205 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1206 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1207 -type f -name '*.ko*' | while read mod; do
1208 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1209 uncompress $mod > $f
1210 grep -q alias=pci: $f || rm -f $f
1211 done
1212 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1213 f=$(basename $i)..z
1214 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1215 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1216 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1217 for j in $deps; do
1218 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1219 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1220 done
1221 done
1222 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"
1223 _n 'List of URLs to insert: '
1224 read -t 30 urliso2
1225 urliso="$urliso2 $urliso"
1226 fi
1227 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1228 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1229 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1230 else
1231 cp /bin/busybox $TMP_DIR/initfs/bin
1232 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1233 cp /sbin/insmod $TMP_DIR/initfs/bin
1234 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1235 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1236 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1237 fi
1238 need_lib=true
1239 fi
1240 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1241 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1242 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1243 done
1244 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1245 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1246 $TMP_DIR/initfs/lib/modules 2>/dev/null
1247 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1248 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1249 cp -a $i $TMP_DIR/initfs/dev
1250 done
1251 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1252 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1253 cp -a $i $TMP_DIR/initfs/dev
1254 done 2>/dev/null
1255 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1256 cp -a $i $TMP_DIR/initfs/lib
1257 done
1258 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1259 #!/bin/sh
1261 getarg() {
1262 grep -q " \$1=" /proc/cmdline || return 1
1263 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1264 return 0
1267 copy_rootfs() {
1268 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1269 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1270 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1271 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1272 path=/mnt/
1273 return 0
1274 else
1275 rm -f /mnt/rootfs*
1276 return 1
1277 fi
1280 echo "Switching / to tmpfs..."
1281 mount -t proc proc /proc
1282 size="\$(grep rootfssize= < /proc/cmdline | \\
1283 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1284 [ -n "\$size" ] || size="-o size=90%"
1286 mount -t sysfs sysfs /sys
1287 for i in /lib/modules/*.ko ; do
1288 echo -en "Probe \$i \\r"
1289 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1290 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1291 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1292 insmod /lib/modules/\$k.ko 2> /dev/null
1293 done
1294 echo "Loading \$i"
1295 insmod \$i 2> /dev/null
1296 break
1297 done
1298 done
1299 umount /sys
1300 while read var default; do
1301 eval \$var=\$default
1302 getarg \$var \$var
1303 done <<EOT
1304 eth eth0
1305 dns 208.67.222.222,208.67.220.220
1306 netmask 255.255.255.0
1307 gw
1308 ip
1309 EOT
1310 grep -q \$eth /proc/net/dev || sh
1311 if [ -n "\$ip" ]; then
1312 ifconfig \$eth \$ip netmask \$netmask up
1313 route add default gateway \$gw
1314 for i in \$(echo \$dns | sed 's/,/ /g'); do
1315 echo "nameserver \$i" >> /etc/resolv.conf
1316 done
1317 else
1318 udhcpc -f -q -s /lib/udhcpc -i \$eth
1319 fi
1320 for i in $urliso ; do
1321 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1322 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"
1323 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1324 done
1325 getarg urliso URLISO
1326 DIR=fs
1327 if getarg loram DIR; then
1328 DEVICE=\${DIR%,*}
1329 DIR=/\${DIR#*,}
1330 fi
1331 mount -t tmpfs \$size tmpfs /mnt
1332 path2=/mnt/.httpfs/
1333 path=/mnt/.cdrom/
1334 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1335 while [ ! -d \$path/boot ]; do
1336 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1337 httpfs \$i \$path2 && echo \$i && break
1338 done
1339 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1340 done
1342 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1343 umount /proc
1344 branch=:/mnt/.cdrom/\$DIR
1345 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1346 branch=
1347 lp=1
1348 insmod /lib/modules/squashfs.ko 2> /dev/null
1349 for i in \${path}boot/rootfs?.* ; do
1350 fs=\${i#*root}
1351 branch=\$branch:/mnt/.\$fs
1352 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1353 losetup -o 124 /dev/loop\$lp \$i
1354 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1355 lp=\$((\$lp+1))
1356 done
1357 fi
1358 mkdir -p /mnt/.rw/mnt/.httpfs
1359 while read type opt; do
1360 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1361 done <<EOT
1362 aufs br=/mnt/.rw\$branch
1363 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1364 EOT
1365 rm -rf /lib/modules
1366 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1367 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1368 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1369 EOTEOT
1370 chmod +x $TMP_DIR/initfs/init
1371 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1372 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1373 rm -f $i
1374 done 2>/dev/null
1375 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1376 lzma e $TMP_DIR/initfs.gz -si
1377 lzma_set_size $TMP_DIR/initfs.gz
1378 rm -rf $TMP_DIR/initfs
1379 align_to_32bits $TMP_DIR/initfs.gz
1380 return 0
1384 # Move each initramfs to squashfs
1386 build_loram_rootfs() {
1387 rootfs_sizes=""
1388 for i in $TMP_DIR/iso/boot/rootfs*; do
1389 mkdir -p $TMP_DIR/fs
1390 cd $TMP_DIR/fs
1391 uncompress $i | cpio -idm
1392 deduplicate
1393 cd - > /dev/null
1394 rootfs=$TMP_DIR/$(basename $i)
1395 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1396 cd $TMP_DIR
1397 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1398 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1399 rm -f $rootfs
1400 mv $rootfs.cpio $rootfs
1401 cd - > /dev/null
1402 rm -rf $TMP_DIR/fs
1403 done
1407 # Move meta boot configuration files to basic configuration files
1408 # because meta loram flavor is useless when rootfs is not loaded in RAM
1410 unmeta_boot() {
1411 local root=${1:-$TMP_DIR/loramiso}
1412 if [ -f $root/boot/isolinux/noram.cfg ]; then
1413 # We keep enough information to do unloram...
1414 [ -s $root/boot/isolinux/common.cfg ] &&
1415 sed -i 's/label slitaz/label orgslitaz/' \
1416 $root/boot/isolinux/common.cfg
1417 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1418 shift
1419 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1420 $root/boot/isolinux/isolinux.cfg
1421 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1422 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1423 $root/boot/isolinux/*.cfg
1424 fi
1428 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1429 # These squashfs may be loaded in RAM at boot time.
1430 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1431 # Meta flavors are converted to normal flavors.
1433 build_loram_cdrom() {
1434 build_initfs cdrom || return 1
1435 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1436 mkdir $TMP_DIR/loramiso/fs
1437 cd $TMP_DIR/loramiso/fs
1438 for i in $( ls ../boot/root* | sort -r ) ; do
1439 uncompress $i | cpio -idmu
1440 rm -f $i
1441 done
1442 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1443 cd - >/dev/null
1444 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1445 unmeta_boot
1446 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1447 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1448 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1449 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1450 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1451 create_iso $OUTPUT $TMP_DIR/loramiso
1455 # Create http bootstrap to load and remove loram_cdrom
1456 # Meta flavors are converted to normal flavors.
1458 build_loram_http() {
1459 build_initfs http || return 1
1460 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1461 rm -f $TMP_DIR/loramiso/boot/rootfs*
1462 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1463 unmeta_boot
1464 create_iso $OUTPUT $TMP_DIR/loramiso
1468 # Update meta flavor selection sizes.
1469 # Reduce sizes with rootfs gains.
1471 update_metaiso_sizes() {
1472 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1473 do
1474 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1475 local sizes="$rootfs_sizes"
1476 local new
1477 set -- $append
1478 shift
1479 [ "$1" == "ifmem" ] && shift
1480 new=""
1481 while [ -n "$2" ]; do
1482 local s
1483 case "$1" in
1484 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1485 *M) s=$(( ${1%M} * 1024 ));;
1486 *) s=${1%K};;
1487 esac
1488 sizes=${sizes#* }
1489 for i in $sizes ; do
1490 s=$(( $s - $i ))
1491 done
1492 new="$new $s $2"
1493 shift 2
1494 done
1495 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1496 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1497 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1498 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1499 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1500 done
1504 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1505 # Meta flavor selection sizes are updated.
1507 build_loram_ram() {
1508 build_initfs ram || return 1
1509 build_loram_rootfs "$1"
1510 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1511 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1512 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1513 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1514 update_metaiso_sizes
1515 create_iso $OUTPUT $TMP_DIR/loramiso
1519 # Remove files installed by packages
1521 find_flavor_rootfs() {
1522 for i in $1/etc/tazlito/*.extract; do
1523 [ -e $i ] || continue
1524 chroot $1 /bin/sh ${i#$1}
1525 done
1527 # Clean hardlinks and files patched by genisofs in /boot
1528 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1529 rm -f $1/boot/$i*
1530 done
1532 # Clean files generated in post_install
1533 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1534 $1/dev/core $1/dev/fd $1/dev/std*
1536 # Verify md5
1537 cat $1$INSTALLED/*/md5sum | \
1538 while read md5 file; do
1539 [ -e "$1$file" ] || continue
1540 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1541 rm -f "$1$file"
1542 done
1544 # Check configuration files
1545 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1546 [ -e $i ] || continue
1547 mkdir /tmp/volatile$$
1548 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1549 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1550 while read file ; do
1551 [ -e "$1/$file" ] || continue
1552 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1553 done
1554 rm -rf /tmp/volatile$$
1555 done
1557 # Remove other files blindly
1558 for i in $1$INSTALLED/*/files.list; do
1559 for file in $(cat "$i"); do
1560 [ "$1$file" -nt "$i" ] && continue
1561 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1562 [ -d "$1$file" ] || rm -f "$1$file"
1563 done
1564 done
1566 # Remove tazpkg files and tmp files
1567 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1568 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1569 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1570 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1571 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1573 # Cleanup directory tree
1574 cd $1
1575 find * -type d | sort -r | while read dir; do
1576 rmdir "$dir" 2>/dev/null
1577 done
1578 cd - > /dev/null
1582 # Get byte(s) from a binary file
1584 get() {
1585 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1589 # Get cpio flavor info from the ISO image
1591 flavordata() {
1592 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1593 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1597 # Restore undigest mirrors
1599 restore_mirrors() {
1600 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1601 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1603 action 'Restoring mirrors...'
1604 if [ -d "$undigest.bak" ]; then
1605 [ -d "$undigest" ] && rm -r "$undigest"
1606 mv "$undigest.bak" "$undigest"
1607 fi
1608 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1609 :; status
1613 # Setup undigest mirrors
1615 setup_mirrors() {
1616 # Setup mirrors in plain system or in chroot (with variable root=)
1617 local mirrorlist="$1" fresh repacked
1618 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1620 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1621 restore_mirrors
1623 _ 'Setting up mirrors for %s...' "$root/"
1624 # Backing up current undigest mirrors and priority
1625 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1626 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1627 rm -rf '/var/www/tazlito/'
1628 mkdir -p '/var/www/tazlito/'
1630 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1631 fresh='/home/slitaz/packages'
1632 if [ -d "$fresh" ]; then
1633 # Setup first undigest mirror
1634 mkdir -p "$undigest/fresh"
1635 echo "$fresh" > "$undigest/fresh/mirror"
1636 echo 'fresh' >> "$priority"
1637 # Rebuild mirror DB if needed
1638 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1639 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1640 tazpkg mkdb "$fresh" --forced --root=''
1641 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1642 fi
1644 # Repacked packages: high priority
1645 repacked="$PACKAGES_REPOSITORY"
1646 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1647 # According to Tazlito setup file (tazlito.conf):
1648 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1649 # or
1650 # WORK_DIR="/home/slitaz"
1651 # and
1652 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1653 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1655 # Setup second undigest mirror
1656 mkdir -p "$undigest/repacked"
1657 echo "$repacked" > "$undigest/repacked/mirror"
1658 echo 'repacked' >> "$priority"
1659 # Rebuild mirror DB if needed
1660 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1661 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1662 tazpkg mkdb "$repacked" --forced --root=''
1663 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1664 fi
1666 # All repositories listed in mirrors list: normal priority
1667 [ -e "$mirrorlist" ] && \
1668 while read mirror; do
1669 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1670 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1671 mkdir -p "$undigest/$mirrorid"
1672 echo "$mirror" > "$undigest/$mirrorid/mirror"
1673 echo "$mirrorid" >> "$priority"
1674 done < "$mirrorlist"
1676 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1678 # Show list of mirrors
1679 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1680 function show(num, name, url) {
1681 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1684 num++;
1685 "cat " db "/undigest/" $0 "/mirror" | getline url;
1686 show(num, $0, url);
1688 END {
1689 num++;
1690 "cat " db "/mirror" | getline url;
1691 show(num, "main", url);
1692 }' "$priority"
1694 tazpkg recharge --quiet >/dev/null
1698 # Get list of 'packages.info' lists using priority
1700 pi_lists() {
1701 local pi
1702 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1703 local priority="$root$LOCALSTATE/priority"
1704 local undigest="$root$LOCALSTATE/undigest"
1707 [ -s "$priority" ] && cat "$priority"
1708 echo 'main'
1709 [ -d "$undigest" ] && ls "$undigest"
1710 } | awk -vun="$undigest/" '
1712 if (arr[$0] != 1) {
1713 arr[$0] = 1;
1714 print un $0 "/packages.info";
1716 }' | sed 's|/undigest/main||' | \
1717 while read pi; do
1718 [ -e "$pi" ] && echo "$pi"
1719 done
1723 # Strip versions from packages list
1725 strip_versions() {
1726 if [ -n "$stripped" ]; then
1727 action 'Consider list %s already stripped' "$(basename "$1")"
1728 status
1729 return 0
1730 fi
1731 action 'Strip versions from list %s...' "$(basename "$1")"
1732 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1733 [ -f "$in_list" ] || die "List '$in_list' not found."
1735 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1736 awk '
1738 if (FILENAME ~ "packages.info") {
1739 # Collect package names
1740 FS = "\t"; pkg[$1] = 1;
1741 } else {
1742 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1743 while (NF > 1 && ! pkg[$0])
1744 NF --;
1745 printf "%s\n", $0;
1747 }' $(pi_lists) "$in_list" > "$tmp_list"
1749 cat "$tmp_list" > "$in_list"
1750 rm "$tmp_list"
1751 status
1755 # Display list of unknown packages (informative)
1757 display_unknown() {
1758 [ -s "$1" ] || return
1759 echo "Unknown packages:" >&2
1760 cat "$1" >&2
1761 rm "$1"
1765 # Display warnings about critical packages absent (informative)
1767 display_warn() {
1768 [ -s "$1" ] || return
1769 echo "Absent critical packages:" >&2
1770 cat "$1" >&2
1771 rm "$1"
1772 echo "Probably ISO image will be unusable."
1776 # Install packages to rootfs
1778 install_list_to_rootfs() {
1779 local list="$1" rootfs="$2" pkg i ii
1780 local undigest="$rootfs/var/lib/tazpkg/undigest"
1782 # initial tazpkg setup in empty rootfs
1783 tazpkg --root=$rootfs >/dev/null 2>&1
1784 # pass current 'mirror' to the rootfs
1785 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1786 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1787 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1788 # link rootfs packages cache to the regular packages cache
1789 rm -r "$rootfs/var/cache/tazpkg"
1790 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1792 setup_mirrors mirrors
1794 # Just in case if flavor not contains "tazlito" package
1795 mkdir -p "$rootfs/etc/tazlito"
1797 newline
1799 # Choose detailed log with --detailed
1800 if [ -n "$detailed" ]; then
1801 while read pkg; do
1802 separator '-'
1803 echo $pkg
1804 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1805 done < $list
1806 separator '='
1807 else
1808 while read pkg; do
1809 action 'Installing package: %s' "$pkg"
1810 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1811 status
1812 done < $list
1813 fi
1814 newline
1816 restore_mirrors
1817 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1818 for i in fresh repacked; do
1819 ii="$undigest/$i"
1820 [ -d "$ii" ] && rm -rf "$ii"
1821 ii="$rootfs/var/lib/tazpkg/priority"
1822 if [ -f "$ii" ]; then
1823 sed -i "/$i/d" "$ii"
1824 [ -s "$ii" ] || rm "$ii"
1825 fi
1826 done
1827 [ -d "$undigest" ] && \
1828 for i in $(find "$undigest" -type f); do
1829 # Remove all undigest PKGDB files but 'mirror'
1830 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1831 done
1832 [ -d "$undigest" ] && \
1833 rmdir --ignore-fail-on-non-empty "$undigest"
1835 # Un-link packages cache
1836 rm "$rootfs/var/cache/tazpkg"
1838 # Clean /var/lib/tazpkg
1839 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1845 ####################
1846 # Tazlito commands #
1847 ####################
1849 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1850 case "$0" in
1851 *reduplicate)
1852 find ${@:-.} ! -type d -links +1 \
1853 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1854 exit 0 ;;
1855 *deduplicate)
1856 deduplicate "$@"
1857 exit 0 ;;
1858 esac
1861 case "$COMMAND" in
1862 stats)
1863 # Tazlito general statistics from the config file.
1865 title 'Tazlito statistics'
1866 optlist "\
1867 Config file : $CONFIG_FILE
1868 ISO name : $ISO_NAME.iso
1869 Volume name : $VOLUM_NAME
1870 Prepared : $PREPARED
1871 Packages repository : $PACKAGES_REPOSITORY
1872 Distro directory : $DISTRO
1873 Additional files : $ADDFILES
1874 " | sed '/: $/d'
1875 footer
1876 ;;
1879 list-addfiles)
1880 # Simple list of additional files in the rootfs
1881 newline
1882 if [ -d "$ADDFILES/rootfs" ]; then
1883 cd $ADDFILES
1884 find rootfs -type f
1885 else
1886 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1887 fi
1888 newline
1889 ;;
1892 gen-config)
1893 # Generate a new config file in the current dir or the specified
1894 # directory by $2.
1896 if [ -n "$2" ]; then
1897 mkdir -p "$2" && cd "$2"
1898 fi
1900 newline
1901 action 'Generating empty tazlito.conf...'
1902 empty_config_file
1903 status
1905 separator
1906 if [ -f 'tazlito.conf' ] ; then
1907 _ 'Configuration file is ready to edit.'
1908 _ 'File location: %s' "$(pwd)/tazlito.conf"
1909 newline
1910 fi
1911 ;;
1914 configure)
1915 # Configure a tazlito.conf config file. Start by getting
1916 # a empty config file and sed it.
1918 if [ -f 'tazlito.conf' ]; then
1919 rm tazlito.conf
1920 else
1921 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1922 'or in the same directory of the file you want to configure.'
1923 cd /etc
1924 fi
1926 empty_config_file
1928 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1930 # ISO name.
1931 echo -n "ISO name : " ; read answer
1932 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1933 # Volume name.
1934 echo -n "Volume name : " ; read answer
1935 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1936 # Packages repository.
1937 echo -n "Packages repository : " ; read answer
1938 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1939 # Distro path.
1940 echo -n "Distro path : " ; read answer
1941 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1942 footer "Config file is ready to use."
1943 echo 'You can now extract an ISO or generate a distro.'
1944 newline
1945 ;;
1948 gen-iso)
1949 # Simply generate a new iso.
1951 check_root
1952 verify_rootcd
1953 gen_livecd_isolinux
1954 distro_stats
1955 ;;
1958 gen-initiso)
1959 # Simply generate a new initramfs with a new iso.
1961 check_root
1962 verify_rootcd
1963 gen_initramfs "$ROOTFS"
1964 gen_livecd_isolinux
1965 distro_stats
1966 ;;
1969 extract-distro)
1970 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1972 check_root
1973 ISO_IMAGE="$2"
1974 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1975 'Example:\n tazlito image.iso /path/target'
1977 # Set the distro path by checking for $3 on cmdline.
1978 TARGET="${3:-$DISTRO}"
1980 # Exit if existing distro is found.
1981 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1982 'Please clean the distro tree or change directory path.'
1984 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1986 # Start to mount the ISO.
1987 action 'Mounting ISO image...'
1988 mkdir -p "$TMP_DIR"
1989 # Get ISO file size.
1990 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
1991 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
1992 sleep 2
1993 # Prepare target dir, copy the kernel and the rootfs.
1994 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
1995 status
1997 action 'Copying the Linux kernel...'
1998 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
1999 make_bzImage_hardlink "$TARGET/rootcd/boot"
2000 else
2001 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2002 fi
2003 status
2005 for i in $(ls $TMP_DIR); do
2006 [ "$i" == 'boot' ] && continue
2007 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2008 done
2010 for loader in isolinux syslinux extlinux grub; do
2011 [ -d "$TMP_DIR/boot/$loader" ] || continue
2012 action 'Copying %s files...' "$loader"
2013 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2014 status
2015 done
2017 action 'Copying the rootfs...'
2018 cp $TMP_DIR/boot/rootfs*.?z "$TARGET/rootcd/boot"
2019 status
2021 # Extract initramfs.
2022 cd "$TARGET/rootfs"
2023 action 'Extracting the rootfs...'
2024 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
2025 # unpack /usr
2026 for i in etc/tazlito/*.extract; do
2027 [ -f "$i" ] && . $i ../rootcd
2028 done
2029 # Umount and remove temp directory and cd to $TARGET to get stats.
2030 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2031 cd ..
2032 status
2034 newline
2035 separator
2036 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2037 echo "Distro tree : $(pwd)"
2038 echo "Rootfs size : $(du -sh rootfs)"
2039 echo "Rootcd size : $(du -sh rootcd)"
2040 footer
2041 ;;
2044 list-flavors)
2045 # Show available flavors.
2046 list='/etc/tazlito/flavors.list'
2047 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2048 title 'List of flavors'
2049 cat $list
2050 footer
2051 ;;
2054 show-flavor)
2055 # Show flavor description.
2056 set -e
2057 flavor=${2%.flavor}
2058 flv_dir="$(extract_flavor "$flavor")"
2059 desc="$flv_dir/$flavor.desc"
2060 if [ -n "$brief" ]; then
2061 if [ -z "$noheader" ]; then
2062 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2063 separator
2064 fi
2065 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2066 "$(field ISO "$desc")" \
2067 "$(field Rootfs "$desc")" \
2068 "$(field Description "$desc")"
2069 else
2070 separator
2071 cat "$desc"
2072 fi
2073 cleanup
2074 ;;
2077 gen-liveflavor)
2078 # Generate a new flavor from the live system.
2079 FLAVOR=${2%.flavor}
2080 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2082 case "$FLAVOR" in
2083 -?|-h*|--help)
2084 cat <<EOT
2085 SliTaz Live Tool - Version: $VERSION
2087 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2089 $(boldify '<flavor-patch-file> format:')
2090 $(optlist "\
2091 code data
2092 + package to add
2093 - package to remove
2094 ! non-free package to add
2095 ? display message
2096 @ flavor description
2097 ")
2099 $(boldify 'Example:')
2100 $(optlist "\
2101 @ Developer tools for SliTaz maintainers
2102 + slitaz-toolchain
2103 + mercurial
2104 ")
2105 EOT
2106 exit 1
2107 ;;
2108 esac
2109 mv /etc/tazlito/distro-packages.list \
2110 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2111 rm -f distro-packages.list non-free.list 2>/dev/null
2112 tazpkg recharge
2114 DESC=""
2115 [ -n "$3" ] && \
2116 while read action pkg; do
2117 case "$action" in
2118 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2119 -) yes | tazpkg remove $pkg ;;
2120 !) echo $pkg >> non-free.list ;;
2121 @) DESC="$pkg" ;;
2122 \?) echo -en "$pkg"; read action ;;
2123 esac
2124 done < $3
2126 yes '' | tazlito gen-distro
2127 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2128 mv /etc/tazlito/distro-packages.list.$$ \
2129 /etc/tazlito/distro-packages.list 2>/dev/null
2130 ;;
2133 gen-flavor)
2134 # Generate a new flavor from the last ISO image generated
2135 FLAVOR=${2%.flavor}
2136 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2138 title 'Flavor generation'
2139 check_rootfs
2140 FILES="$FLAVOR.pkglist"
2142 action 'Creating file %s...' "$FLAVOR.flavor"
2143 for i in rootcd rootfs; do
2144 if [ -d "$ADDFILES/$i" ] ; then
2145 FILES="$FILES\n$FLAVOR.$i"
2146 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2147 fi
2148 done
2149 status
2151 answer=$(grep -s ^Description $FLAVOR.desc)
2152 answer=${answer#Description : }
2153 if [ -z "$answer" ]; then
2154 echo -n "Description: "
2155 read answer
2156 fi
2158 action 'Compressing flavor %s...' "$FLAVOR"
2159 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2160 echo "Description : $answer" >> $FLAVOR.desc
2161 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2162 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2163 for i in $(ls $ROOTFS$INSTALLED); do
2164 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2165 EXTRAVERSION=""
2166 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2167 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2168 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2169 echo "$i" >> $FLAVOR.nonfree
2170 else
2171 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2172 fi
2173 done
2174 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2175 for i in $LOCALSTATE/undigest/*/mirror ; do
2176 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2177 done
2178 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2179 touch -t 197001010100.00 $FLAVOR.*
2180 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2181 rm $(echo -e $FILES)
2182 status
2184 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2185 ;;
2188 upgrade-flavor)
2189 # Strip versions from pkglist and update estimated numbers in flavor.desc
2190 flavor="${2%.flavor}"
2191 set -e
2192 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2193 set +e
2195 flv_dir="$(extract_flavor "$flavor")"
2197 strip_versions "$flv_dir/$flavor.pkglist"
2199 action 'Updating %s...' "$flavor.desc"
2201 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2202 set -- $(module calc_sizes "$flv_dir" "$flavor")
2203 restore_mirrors >/dev/null
2205 sed -i -e '/Image is ready/d' \
2206 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2207 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2208 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2209 -e "s|\(Packages *:\).*$|\1 $4|" \
2210 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2211 "$flv_dir/$flavor.desc"
2213 pack_flavor "$flv_dir" "$flavor"
2214 status
2215 display_unknown "$flv_dir/err"
2216 display_warn "$flv_dir/warn"
2217 cleanup
2218 ;;
2221 extract-flavor)
2222 # Extract a flavor into $FLAVORS_REPOSITORY
2223 flavor="${2%.flavor}"
2224 set -e
2225 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2226 set +e
2228 action 'Extracting %s...' "$flavor.flavor"
2229 flv_dir="$(extract_flavor "$flavor" full)"
2230 storage="$FLAVORS_REPOSITORY/$flavor"
2232 rm -rf "$storage" 2>/dev/null
2233 mkdir -p "$storage"
2234 cp -a "$flv_dir"/* "$storage"
2235 rm "$storage/description"
2236 status
2238 strip_versions "$storage/packages.list"
2240 cleanup
2241 ;;
2244 pack-flavor)
2245 # Create a flavor from $FLAVORS_REPOSITORY.
2246 flavor=${2%.flavor}
2247 storage="$FLAVORS_REPOSITORY/$flavor"
2249 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2251 action 'Creating flavor %s...' "$flavor"
2252 tmp_dir="$(mktemp -d)"
2254 while read from to; do
2255 [ -s "$storage/$from" ] || continue
2256 cp -a "$storage/$from" "$tmp_dir/$to"
2257 done <<EOT
2258 mirrors $flavor.mirrors
2259 distro.sh $flavor-distro.sh
2260 receipt $flavor.receipt
2261 non-free.list $flavor.nonfree
2262 EOT
2264 # Build the package list.
2265 # It can include a list from another flavor with the keyword @include
2266 if [ -s "$storage/packages.list" ]; then
2267 include=$(grep '^@include' "$storage/packages.list")
2268 if [ -n "$include" ]; then
2269 include=${include#@include }
2270 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2271 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2272 else
2273 echo -e "\nERROR: Can't find include package list from $include\n"
2274 fi
2275 fi
2276 # Generate the final/initial package list
2277 [ -s "$storage/packages.list" ] && \
2278 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2279 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2280 fi
2282 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2283 # Process multi-rootfs flavor
2284 . "$storage/receipt"
2285 set -- $ROOTFS_SELECTION
2286 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2287 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2288 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2290 for i in rootcd rootfs; do
2291 mkdir "$tmp_dir/$i"
2292 # Copy extra files from the first flavor
2293 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2294 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2295 # Overload extra files by meta flavor
2296 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2297 [ -n "$(ls $tmp_dir/$i)" ] &&
2298 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2299 dogzip "$tmp_dir/$flavor.$i"
2300 rm -rf "$tmp_dir/$i"
2301 done
2302 else
2303 # Process plain flavor
2304 for i in rootcd rootfs; do
2305 [ -d "$storage/$i" ] || continue
2306 (cd "$storage/$i";
2307 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2308 done
2309 fi
2311 unset VERSION MAINTAINER ROOTFS_SELECTION
2312 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2313 ROOTFS_SIZE="$1 (estimated)"
2314 INITRAMFS_SIZE="$2 (estimated)"
2315 ISO_SIZE="$3 (estimated)"
2316 PKGNUM="$4"
2317 . "$storage/receipt"
2319 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2320 Flavor : $FLAVOR
2321 Description : $SHORT_DESC
2322 Version : $VERSION
2323 Maintainer : $MAINTAINER
2324 LiveCD RAM size : $FRUGAL_RAM
2325 Rootfs list : $ROOTFS_SELECTION
2326 Build date : $(date '+%Y%m%d at %T')
2327 Packages : $PKGNUM
2328 Rootfs size : $ROOTFS_SIZE
2329 Initramfs size : $INITRAMFS_SIZE
2330 ISO image size : $ISO_SIZE
2331 ================================================================================
2333 EOT
2335 rm -f $tmp_dir/packages.list
2336 pack_flavor "$tmp_dir" "$flavor"
2337 status
2338 display_unknown "$tmp_dir/err"
2339 display_warn "$flv_dir/warn"
2340 cleanup
2341 ;;
2344 get-flavor)
2345 # Get a flavor's files and prepare for gen-distro.
2346 flavor=${2%.flavor}
2347 title 'Preparing %s distro flavor' "$flavor"
2348 set -e
2349 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2350 set +e
2352 action 'Cleaning %s...' "$DISTRO"
2353 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2354 # Clean old files
2355 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2356 [ -f "$i" ] && rm "$i"
2357 done
2358 mkdir -p "$DISTRO"
2359 status
2361 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2363 action 'Extracting flavor %s...' "$flavor.flavor"
2364 flv_dir="$(extract_flavor "$flavor" info)"
2365 cp -a "$flv_dir"/* .
2366 mv packages.list distro-packages.list
2367 mv -f info /etc/tazlito
2368 status
2370 for i in rootcd rootfs; do
2371 if [ -d "$i" ]; then
2372 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2373 fi
2374 done
2376 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2377 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2379 action 'Updating %s...' 'tazlito.conf'
2380 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2381 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2382 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2383 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2384 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2385 status
2387 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2388 cleanup
2389 ;;
2392 iso2flavor)
2393 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2394 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2396 FLAVOR=${3%.flavor}
2397 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2398 mount -o loop,ro $2 $TMP_DIR/iso
2399 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2400 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2401 ! -s $TMP_DIR/flavor/*.desc ]; then
2402 _ 'META flavors are not supported.'
2403 umount -d $TMP_DIR/iso
2404 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2405 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2406 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2407 umount -d $TMP_DIR/iso
2408 else
2409 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2410 uncompress $i | \
2411 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2412 done
2413 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2414 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2415 '/etc/slitaz-release' '/boot/rootfs.gz'
2416 umount -d $TMP_DIR/iso
2417 else
2418 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2419 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2420 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2421 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2422 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2423 umount -d $TMP_DIR/iso
2424 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2425 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2426 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2427 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2428 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2429 < $TMP_DIR/rootfs$INSTALLED.md5
2430 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2431 if [ -s $TMP_DIR/flavor/*desc ]; then
2432 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2433 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2434 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2435 for i in rootfs rootcd ; do
2436 [ -s $TMP_DIR/flavor/*.list$i ] &&
2437 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2438 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2439 done
2440 else
2441 find_flavor_rootfs $TMP_DIR/rootfs
2442 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2443 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2444 for i in rootfs rootcd ; do
2445 [ "$(ls $TMP_DIR/$i)" ] &&
2446 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2447 done
2448 unset VERSION MAINTAINER
2449 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2450 if [ -n "$DESCRIPTION" ]; then
2451 _n 'Flavor version : '; read -t 30 VERSION
2452 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2453 fi
2455 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2456 Flavor : $FLAVOR
2457 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2458 Version : ${VERSION:-1.0}
2459 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2460 LiveCD RAM size : $RAM_SIZE
2461 Build date : $BUILD_DATE
2462 Packages : $PKGCNT
2463 Rootfs size : $ROOTFS_SIZE
2464 Initramfs size : $INITRAMFS_SIZE
2465 ISO image size : $ISO_SIZE
2466 ================================================================================
2468 EOT
2469 longline "Tazlito can't detect each file installed during \
2470 a package post_install. You should extract this flavor (tazlito extract-flavor \
2471 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2472 tree and remove files generated by post_installs.
2473 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2474 repack the flavor (tazlito pack-flavor $FLAVOR)"
2475 fi
2476 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2477 fi
2478 fi
2479 rm -rf $TMP_DIR
2480 ;;
2483 gen-distro)
2484 # Generate a live distro tree with a set of packages.
2486 check_root
2487 start_time=$(date +%s)
2489 # Tazlito options: --iso or --cdrom
2490 CDROM=''
2491 [ -n "$iso" ] && CDROM="-o loop $iso"
2492 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2494 # Check if a package list was specified on cmdline.
2495 if [ -f "$2" ]; then
2496 LIST_NAME="$2"
2497 else
2498 LIST_NAME='distro-packages.list'
2499 fi
2501 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2502 'Please clean the distro tree or change directory path.'
2503 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2504 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2506 # If list not given: build list with all installed packages
2507 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2508 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2509 fi
2511 # Exit if no list name.
2512 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2514 # Start generation.
2515 title 'Tazlito generating a distro'
2517 # Misc checks
2518 mkdir -p "$PACKAGES_REPOSITORY"
2519 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2520 newline
2522 # Mount CD-ROM to be able to repack boot-loader packages
2523 if [ ! -e /boot -a -n "$CDROM" ]; then
2524 mkdir $TMP_MNT
2525 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2526 ln -s "$TMP_MNT/boot" /
2527 if [ ! -d "$ADDFILES/rootcd" ] ; then
2528 mkdir -p "$ADDFILES/rootcd"
2529 for i in $(ls $TMP_MNT); do
2530 [ "$i" == 'boot' ] && continue
2531 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2532 done
2533 fi
2534 else
2535 rmdir "$TMP_MNT"
2536 fi
2537 fi
2539 # Rootfs stuff.
2540 echo 'Preparing the rootfs directory...'
2541 mkdir -p "$ROOTFS"
2542 export root="$ROOTFS"
2543 # pass current 'mirror' to the root
2544 mkdir -p $root/var/lib/tazpkg $root/etc
2545 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2546 cp -f /etc/slitaz-release $root/etc/slitaz-release
2547 strip_versions "$LIST_NAME"
2549 if [ "$REPACK" == 'y' ]; then
2550 # Determine full packages list with all dependencies
2551 tmp_dir="$(mktemp -d)"
2552 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2553 touch "$tmp_dir/full.pkglist"
2554 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2556 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2557 while read pkgname pkgver; do
2558 # Is package in full list?
2559 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2560 # Is package already repacked?
2561 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2562 _ 'Repacking %s...' "$pkgname-$pkgver"
2563 tazpkg repack "$pkgname" --quiet
2564 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2565 status
2566 done
2568 rm -r "$tmp_dir"
2569 fi
2571 if [ -f non-free.list ]; then
2572 # FIXME: working in the ROOTFS chroot?
2573 newline
2574 echo 'Preparing non-free packages...'
2575 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2576 for pkg in $(cat 'non-free.list'); do
2577 if [ ! -d "$INSTALLED/$pkg" ]; then
2578 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2579 tazpkg get-install get-$pkg
2580 fi
2581 get-$pkg "$ROOTFS"
2582 fi
2583 tazpkg repack $pkg
2584 pkg=$(ls $pkg*.tazpkg)
2585 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2586 mv $pkg $PACKAGES_REPOSITORY
2587 done
2588 fi
2589 cp $LIST_NAME $DISTRO/distro-packages.list
2590 newline
2592 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2594 cd $DISTRO
2595 cp distro-packages.list $ROOTFS/etc/tazlito
2596 # Copy all files from $ADDFILES/rootfs to the rootfs.
2597 if [ -d "$ADDFILES/rootfs" ] ; then
2598 action 'Copying addfiles content to the rootfs...'
2599 cp -a $ADDFILES/rootfs/* $ROOTFS
2600 status
2601 fi
2603 action 'Root filesystem is generated...'; status
2605 # Root CD part.
2606 action 'Preparing the rootcd directory...'
2607 mkdir -p $ROOTCD
2608 status
2610 # Move the boot dir with the Linux kernel from rootfs.
2611 # The efi & boot dirs go directly on the CD.
2612 if [ -d "$ROOTFS/efi" ] ; then
2613 action 'Moving the efi directory...'
2614 mv $ROOTFS/efi $ROOTCD
2615 status
2616 fi
2617 if [ -d "$ROOTFS/boot" ] ; then
2618 action 'Moving the boot directory...'
2619 mv $ROOTFS/boot $ROOTCD
2620 cd $ROOTCD/boot
2621 rm -rf grub*
2622 make_bzImage_hardlink
2623 status
2624 fi
2625 cd $DISTRO
2626 # Copy all files from $ADDFILES/rootcd to the rootcd.
2627 if [ -d "$ADDFILES/rootcd" ] ; then
2628 action 'Copying addfiles content to the rootcd...'
2629 cp -a $ADDFILES/rootcd/* $ROOTCD
2630 status
2631 fi
2632 # Execute the distro script used to perform tasks in the rootfs
2633 # before compression. Give rootfs path in arg
2634 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2635 if [ -x "$DISTRO_SCRIPT" ]; then
2636 echo 'Executing distro script...'
2637 sh $DISTRO_SCRIPT $DISTRO
2638 fi
2640 # Execute the custom_rules() found in receipt.
2641 if [ -s "$TOP_DIR/receipt" ]; then
2642 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2643 echo -e "Executing: custom_rules()\n"
2644 . "$TOP_DIR/receipt"
2645 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2646 fi
2647 fi
2649 # Multi-rootfs
2650 if [ -s /etc/tazlito/rootfs.list ]; then
2652 FLAVOR_LIST="$(awk '{
2653 for (i = 2; i <= NF; i+=2)
2654 printf "%s ", $i;
2655 }' /etc/tazlito/rootfs.list)"
2657 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2658 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2659 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2661 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2662 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2663 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2664 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2666 n=0
2667 last=$ROOTFS
2668 while read flavor; do
2669 n=$(($n+1))
2670 mkdir ${ROOTFS}0$n
2671 export root="${ROOTFS}0$n"
2672 # initial tazpkg setup in empty rootfs
2673 tazpkg --root=$root >/dev/null 2>&1
2675 newline
2676 boldify "Building $flavor rootfs..."
2678 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2679 cp "$TOP_DIR/$flavor.flavor" .
2681 if [ ! -s "$flavor.flavor" ]; then
2682 # We may have it in $FLAVORS_REPOSITORY
2683 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2684 tazlito pack-flavor $flavor
2685 else
2686 download $flavor.flavor
2687 fi
2688 fi
2690 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2691 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2692 cp $flavor.pkglist $DISTRO/list-packages0$n
2693 status
2695 strip_versions "$DISTRO/list-packages0$n"
2697 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2699 rm -rf ${ROOTFS}0$n/boot
2701 cd $DISTRO
2702 if [ -s $flavor.rootfs ]; then
2703 _n 'Adding %s rootfs extra files...' "$flavor"
2704 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2705 fi
2707 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2708 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2709 status
2711 rm -f $flavor.flavor install-list
2712 mergefs ${ROOTFS}0$n $last
2713 last=${ROOTFS}0$n
2714 done <<EOT
2715 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2716 EOT
2717 #'
2718 i=$(($n+1))
2719 while [ $n -gt 0 ]; do
2720 mv ${ROOTFS}0$n ${ROOTFS}$i
2721 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2722 gen_initramfs ${ROOTFS}$i
2723 n=$(($n-1))
2724 i=$(($i-1))
2725 export LZMA_HISTORY_BITS=26
2726 done
2727 mv $ROOTFS ${ROOTFS}$i
2728 gen_initramfs ${ROOTFS}$i
2729 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2730 else
2731 # Initramfs and ISO image stuff.
2732 gen_initramfs $ROOTFS
2733 fi
2734 gen_livecd_isolinux
2735 distro_stats
2736 cleanup
2737 ;;
2740 clean-distro)
2741 # Remove old distro tree.
2743 check_root
2744 title 'Cleaning: %s' "$DISTRO"
2745 if [ -d "$DISTRO" ] ; then
2746 if [ -d "$ROOTFS" ] ; then
2747 action 'Removing the rootfs...'
2748 rm -f $DISTRO/$INITRAMFS
2749 rm -rf $ROOTFS
2750 status
2751 fi
2752 if [ -d "$ROOTCD" ] ; then
2753 action 'Removing the rootcd...'
2754 rm -rf $ROOTCD
2755 status
2756 fi
2757 action 'Removing eventual ISO image...'
2758 rm -f $DISTRO/$ISO_NAME.iso
2759 rm -f $DISTRO/$ISO_NAME.md5
2760 status
2761 fi
2762 footer
2763 ;;
2766 check-distro)
2767 # Check for a few LiveCD needed files not installed by packages.
2769 # TODO: Remove this function.
2770 # First two files are maintained by tazpkg while it runs on rootfs,
2771 # while last one file should be maintained by tazlito itself.
2772 check_rootfs
2773 title 'Checking distro: %s' "$ROOTFS"
2774 # SliTaz release info.
2775 rel='/etc/slitaz-release'
2776 if [ ! -f "$ROOTFS$rel" ]; then
2777 _ 'Missing release info: %s' "$rel"
2778 else
2779 action 'Release : %s' "$(cat $ROOTFS$rel)"
2780 status
2781 fi
2782 # Tazpkg mirror.
2783 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2784 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2785 todomsg
2786 else
2787 action 'Mirror configuration exists...'
2788 status
2789 fi
2790 # Isolinux msg
2791 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2792 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2793 todomsg
2794 else
2795 action 'Isolinux message seems good...'
2796 status
2797 fi
2798 footer
2799 ;;
2802 writeiso)
2803 # Writefs to ISO image including /home unlike gen-distro we don't use
2804 # packages to generate a rootfs, we build a compressed rootfs with all
2805 # the current filesystem similar to 'tazusb writefs'.
2807 DISTRO='/home/slitaz/distro'
2808 ROOTCD="$DISTRO/rootcd"
2809 COMPRESSION="${2:-none}"
2810 ISO_NAME="${3:-slitaz}"
2811 check_root
2812 # Start info
2813 title 'Write filesystem to ISO'
2814 longline "The command writeiso will write the current filesystem into a \
2815 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2816 newline
2817 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2819 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2820 # Save some space
2821 rm -rf /var/cache/tazpkg/*
2822 rm -f /var/lib/tazpkg/*.bak
2823 rm -rf $DISTRO
2825 # Optionally remove sound card selection and screen resolution.
2826 if [ -z $LaunchedByTazpanel ]; then
2827 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2828 case $anser in
2829 y)
2830 action 'Removing current sound card and screen configurations...'
2831 rm -f /var/lib/sound-card-driver
2832 rm -f /var/lib/alsa/asound.state
2833 rm -f /etc/X11/xorg.conf ;;
2834 *)
2835 action 'Keeping current sound card and screen configurations...' ;;
2836 esac
2837 status
2838 newline
2840 # Optionally remove i18n settings
2841 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2842 case $anser in
2843 y)
2844 action 'Removing current locale/keymap settings...'
2845 newline > /etc/locale.conf
2846 newline > /etc/keymap.conf ;;
2847 *)
2848 action 'Keeping current locale/keymap settings...' ;;
2849 esac
2850 status
2851 fi
2853 # Clean-up files by default
2854 newline > /etc/udev/rules.d/70-persistent-net.rules
2855 newline > /etc/udev/rules.d/70-persistant-cd.rules
2857 # Create list of files including default user files since it is defined in /etc/passwd
2858 # and some new users might have been added.
2859 cd /
2860 echo 'init' > /tmp/list
2861 for dir in bin etc sbin var dev lib root usr home opt; do
2862 [ -d $dir ] && find $dir
2863 done >> /tmp/list
2865 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2866 [ -d $dir ] && echo $dir
2867 done >> /tmp/list
2869 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2871 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2872 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2873 #fi
2874 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2875 touch /var/log/wtmp
2877 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2878 sed -i "/var\/log\/$removelog/d" /tmp/list
2879 done
2881 # Generate initramfs with specified compression and display rootfs
2882 # size in realtime.
2883 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2885 write_initramfs &
2886 sleep 2
2887 cd - > /dev/null
2888 echo -en "\nFilesystem size:"
2889 while [ ! -f /tmp/rootfs ]; do
2890 sleep 1
2891 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2892 done
2893 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2894 echo -e "\n"
2895 rm -f /tmp/rootfs
2897 # Move freshly generated rootfs to the cdrom.
2898 mkdir -p $ROOTCD/boot
2899 mv -f /$INITRAMFS $ROOTCD/boot
2900 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2902 # Now we need the kernel and isolinux files.
2903 copy_from_cd() {
2904 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2905 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2906 unmeta_boot $ROOTCD
2907 umount /media/cdrom
2910 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2911 copy_from_cd;
2912 elif mount | grep /media/cdrom; then
2913 copy_from_cd;
2914 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2915 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2916 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2917 else
2918 touch /tmp/.write-iso-error
2919 longline "When SliTaz is running in RAM the kernel and bootloader \
2920 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2921 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2922 echo -en "----\nENTER to continue..."; read i
2923 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2924 copy_from_cd
2925 fi
2927 # Generate the iso image.
2928 touch /tmp/.write-iso
2929 newline
2930 cd $DISTRO
2931 create_iso $ISO_NAME.iso $ROOTCD
2932 action 'Creating the ISO md5sum...'
2933 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2934 status
2936 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2937 rm -f /tmp/.write-iso
2939 if [ -z $LaunchedByTazpanel ]; then
2940 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2941 case $anser in
2942 y)
2943 umount /dev/cdrom 2>/dev/null
2944 eject
2945 echo -n "Please insert a blank CD-ROM and press ENTER..."
2946 read i && sleep 2
2947 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2948 echo -en "----\nENTER to continue..."; read i ;;
2949 *)
2950 exit 0 ;;
2951 esac
2952 fi
2953 ;;
2956 burn-iso)
2957 # Guess CD-ROM device, ask user and burn the ISO.
2959 check_root
2960 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2961 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2962 # We can specify an alternative ISO from the cmdline.
2963 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2964 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2966 title 'Tazlito burn ISO'
2967 echo "CD-ROM device : /dev/$DRIVE_NAME"
2968 echo "Drive speed : $DRIVE_SPEED"
2969 echo "ISO image : $iso"
2970 footer
2972 case $(yesorno 'Burn ISO image?' 'n') in
2973 y)
2974 title 'Starting Wodim to burn the ISO...'
2975 sleep 2
2976 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2977 footer 'ISO image is burned to CD-ROM.'
2978 ;;
2979 *)
2980 die 'Exiting. No ISO burned.'
2981 ;;
2982 esac
2983 ;;
2986 merge)
2987 # Merge multiple rootfs into one iso.
2989 if [ -z "$2" ]; then
2990 cat <<EOT
2991 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
2993 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
2994 i.e: rootfsN is a subset of rootfsN-1
2995 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
2996 The boot loader will select the rootfs according to the RAM size detected.
2998 Example:
2999 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3001 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3002 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3004 EOT
3005 exit 2
3006 fi
3008 shift # skip merge
3009 append="$1 slitaz1"
3010 shift # skip size1
3011 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3013 ISO=$1.merged
3015 # Extract filesystems
3016 action 'Mounting %s' "$1"
3017 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3018 status || cleanup_merge
3020 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3021 make_bzImage_hardlink $TMP_DIR/iso/boot
3022 umount -d $TMP_DIR/mnt
3023 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3024 _ '%s is already a merged iso. Aborting.' "$1"
3025 cleanup_merge
3026 fi
3027 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3028 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3029 if [ ! -f /boot/isolinux/ifmem.c32 -a
3030 ! -f /boot/isolinux/c32box.c32 ]; then
3031 cat <<EOT
3032 No file /boot/isolinux/ifmem.c32
3033 Please install syslinux package !
3034 EOT
3035 rm -rf $TMP_DIR
3036 exit 1
3037 fi
3038 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3039 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3040 fi
3042 action 'Extracting %s' 'iso/rootfs.gz'
3043 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3044 [ -d $TMP_DIR/rootfs1/etc ]
3045 status || cleanup_merge
3047 n=1
3048 while [ -n "$2" ]; do
3049 shift # skip rootfs N-1
3050 p=$n
3051 n=$(($n + 1))
3052 append="$append $1 slitaz$n"
3053 shift # skip size N
3054 mkdir -p $TMP_DIR/rootfs$n
3056 action 'Extracting %s' "$1"
3057 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3058 [ -d "$TMP_DIR/rootfs$n/etc" ]
3059 status || cleanup_merge
3061 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3062 action 'Creating %s' "rootfs$p.gz"
3063 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3064 status
3065 done
3066 action 'Creating %s' "rootfs$n.gz"
3067 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3068 status
3069 rm -f $TMP_DIR/iso/boot/rootfs.gz
3070 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3071 create_iso $ISO $TMP_DIR/iso
3072 rm -rf $TMP_DIR
3073 ;;
3076 repack)
3077 # Repack an iso with maximum lzma compression ratio.
3079 ISO=$2
3080 mkdir -p $TMP_DIR/mnt
3082 # Extract filesystems
3083 action 'Mounting %s' "$ISO"
3084 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3085 status || cleanup_merge
3087 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3088 umount -d $TMP_DIR/mnt
3090 for i in $TMP_DIR/iso/boot/rootfs* ; do
3091 action 'Repacking %s' "$(basename $i)"
3092 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3093 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3094 align_to_32bits $i
3095 status
3096 done
3098 create_iso $ISO $TMP_DIR/iso
3099 rm -rf $TMP_DIR
3100 ;;
3103 build-loram)
3104 # Build a Live CD for low RAM systems.
3106 ISO="$2"
3107 OUTPUT="$3"
3108 [ -z "$3" ] && \
3109 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3110 mkdir -p "$TMP_DIR/iso"
3111 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3112 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3113 if ! check_iso_for_loram ; then
3114 umount -d "$TMP_DIR/iso"
3115 die "$ISO is not a valid SliTaz live CD. Abort."
3116 fi
3117 case "$4" in
3118 cdrom) build_loram_cdrom ;;
3119 http) build_loram_http ;;
3120 *) build_loram_ram "$5" ;;
3121 esac
3122 umount $TMP_DIR/iso # no -d: needs /proc
3123 losetup -d $loopdev
3124 rm -rf $TMP_DIR
3125 ;;
3128 emu-iso)
3129 # Emulate an ISO image with Qemu.
3130 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3131 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3132 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3133 echo -e "\nStarting Qemu emulator:\n"
3134 echo -e "qemu $QEMU_OPTS $iso\n"
3135 qemu $QEMU_OPTS $iso
3136 ;;
3139 deduplicate)
3140 # Deduplicate files in a tree
3141 shift
3142 deduplicate "$@"
3143 ;;
3146 usage|*)
3147 # Print usage also for all unknown commands.
3148 usage
3149 ;;
3150 esac
3152 exit 0