tazlito view tazlito @ rev 492

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