tazlito view tazlito @ rev 488

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