tazlito view tazlito @ rev 495

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