tazlito view tazlito @ rev 486

Russian inner dolls should not overwrite /cdrom/boot (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Feb 26 08:13:23 2018 +0100 (2018-02-26)
parents 66335bf0d909
children b5e7737cce0b
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 done
970 unset IFS
971 status
972 }
975 cleanup_merge() {
976 rm -rf $TMP_DIR
977 exit 1
978 }
981 # Update isolinux config files for multiple rootfs
983 update_bootconfig() {
984 local files
985 action 'Updating boot config files...'
986 files="$(grep -l 'include common' $1/*.cfg)"
987 for file in $files; do
988 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
989 if (/label/) label=$0;
990 else if (/kernel/) kernel=$0;
991 else if (/append/) {
992 i=index($0,"rootfs.gz");
993 append=substr($0,i+9);
994 }
995 else if (/include/) {
996 for (i = 1; i <= n; i++) {
997 print label i
998 print kernel;
999 initrd="initrd=/boot/rootfs" n ".gz"
1000 for (j = n - 1; j >= i; j--) {
1001 initrd=initrd ",/boot/rootfs" j ".gz";
1003 printf "\tappend %s%s\n",initrd,append;
1004 print "";
1006 print;
1008 else print;
1009 }' < $file > $file.$$
1010 mv -f $file.$$ $file
1011 done
1012 sel="$(echo $2 | awk '{
1013 for (i=1; i<=NF; i++)
1014 if (i % 2 == 0) printf " slitaz%d", i/2
1015 else printf " %s", $i
1016 }')"
1018 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1020 label slitaz
1021 kernel /boot/isolinux/ifmem.c32
1022 append$sel noram
1024 label noram
1025 config noram.cfg
1027 EOT
1029 # Update vesamenu
1030 if [ -s "$1/isolinux.cfg" ]; then
1031 files="$files $1/isolinux.cfg"
1032 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1033 BEGIN {
1034 kernel = " COM32 c32box.c32"
1037 if (/ROWS/) print "MENU ROWS " n+$3;
1038 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1039 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1040 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1041 else if (/VSHIFT/) {
1042 x = $3-n;
1043 if (x < 0) x = 0;
1044 print "MENU VSHIFT " x;
1046 else if (/rootfs.gz/) {
1047 linux = "";
1048 if (/bzImage/) linux = "linux /boot/bzImage ";
1049 i = index($0, "rootfs.gz");
1050 append = substr($0, i+9);
1051 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1052 printf "\tappend%s noram\n", sel;
1053 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1054 for (i = 1; i <= n; i++) {
1055 print "LABEL slitaz" i
1056 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1057 printf "%s\n", kernel;
1058 initrd = "initrd=/boot/rootfs" n ".gz"
1059 for (j = n - 1; j >= i; j--) {
1060 initrd = initrd ",/boot/rootfs" j ".gz";
1062 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1065 else if (/bzImage/) kernel = $0;
1066 else print;
1067 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1068 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1069 fi
1071 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1072 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1073 cat > $1/noram.cfg <<EOT
1074 implicit 0
1075 prompt 1
1076 timeout 80
1077 $(grep '^F[0-9]' $1/isolinux.cfg)
1079 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1080 say Not enough RAM to boot slitaz. Trying hacker mode...
1081 default hacker
1082 label hacker
1083 KERNEL /boot/bzImage
1084 append rw root=/dev/null vga=normal
1086 label reboot
1087 EOT
1089 if [ -s $1/c32box.c32 ]; then
1090 cat >> $1/noram.cfg <<EOT
1091 COM32 c32box.c32
1092 append reboot
1094 label poweroff
1095 COM32 c32box.c32
1096 append poweroff
1098 EOT
1099 else
1100 echo " com32 reboot.c32" >> $1/noram.cfg
1101 fi
1103 # Restore real label names
1104 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1105 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1106 while read pat; do
1107 sed -i "s/slitaz$pat/" $files
1108 done
1109 status
1113 # Uncompress rootfs or module to stdout
1115 uncompress() {
1116 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1117 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1121 # Install a missing package
1123 install_package() {
1124 if [ -z "$2" ]; then
1125 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1126 else
1127 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1128 fi
1129 case "$answer" in
1130 y)
1131 # We don't want package on host cache.
1132 action 'Getting and installing package: %s' "$1"
1133 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1134 status ;;
1135 *)
1136 return 1 ;;
1137 esac
1141 # Check iso for loram transformation
1143 check_iso_for_loram() {
1144 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1145 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1149 # Build initial rootfs for loram ISO ram/cdrom/http
1151 build_initfs() {
1152 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1153 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1154 mirror3.slitaz.org mirror.slitaz.org"
1155 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1156 [ -z "$version" ] && die "Can't find the kernel version." \
1157 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1159 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1160 need_lib=false
1161 for i in bin dev run mnt proc tmp sys lib/modules; do
1162 mkdir -p $TMP_DIR/initfs/$i
1163 done
1164 ln -s bin $TMP_DIR/initfs/sbin
1165 ln -s . $TMP_DIR/initfs/usr
1166 for aufs in aufs overlayfs; do
1167 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1168 install_package $aufs $version && break
1169 done || return 1
1170 [ -s /init ] || install_package slitaz-boot-scripts
1171 cp /init $TMP_DIR/initfs/
1172 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1173 $TMP_DIR/initfs/lib/modules
1174 if [ "$1" == 'cdrom' ]; then
1175 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1176 else
1177 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1178 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1179 install_package linux-squashfs $version || return 1
1180 done
1181 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1182 $TMP_DIR/initfs/lib/modules
1183 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1184 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1185 fi
1186 if [ "$1" == 'http' ]; then
1187 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1188 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1189 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1190 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1191 cp -a /dev/fuse $TMP_DIR/initfs/dev
1192 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1193 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1194 else
1195 need_lib=true
1196 fi
1197 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1198 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1199 else
1200 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1201 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1202 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1203 cp -a /lib/librt* $TMP_DIR/initfs/lib
1204 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1205 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1206 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1207 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1208 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1209 need_lib=true
1210 fi
1211 cd $TMP_DIR/fs
1212 echo 'Getting slitaz-release & ethernet modules...'
1213 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1214 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1215 [ -s rootfs* ] || continue
1216 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1217 rm -f rootfs*
1218 done 2>&1 > /dev/null
1219 cd - > /dev/null
1220 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1221 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1222 -type f -name '*.ko*' | while read mod; do
1223 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1224 uncompress $mod > $f
1225 grep -q alias=pci: $f || rm -f $f
1226 done
1227 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1228 f=$(basename $i)..z
1229 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1230 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1231 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1232 for j in $deps; do
1233 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1234 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1235 done
1236 done
1237 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"
1238 _n 'List of URLs to insert: '
1239 read -t 30 urliso2
1240 urliso="$urliso2 $urliso"
1241 fi
1242 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1243 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1244 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1245 else
1246 cp /bin/busybox $TMP_DIR/initfs/bin
1247 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1248 cp /sbin/insmod $TMP_DIR/initfs/bin
1249 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1250 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1251 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1252 fi
1253 need_lib=true
1254 fi
1255 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1256 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1257 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1258 done
1259 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1260 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1261 $TMP_DIR/initfs/lib/modules 2>/dev/null
1262 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1263 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1264 cp -a $i $TMP_DIR/initfs/dev
1265 done
1266 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1267 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1268 cp -a $i $TMP_DIR/initfs/dev
1269 done 2>/dev/null
1270 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1271 cp -a $i $TMP_DIR/initfs/lib
1272 done
1273 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1274 #!/bin/sh
1276 getarg() {
1277 grep -q " \$1=" /proc/cmdline || return 1
1278 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1279 return 0
1282 copy_rootfs() {
1283 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1284 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1285 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1286 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1287 path=/mnt/
1288 return 0
1289 else
1290 rm -f /mnt/rootfs*
1291 return 1
1292 fi
1295 echo "Switching / to tmpfs..."
1296 mount -t proc proc /proc
1297 size="\$(grep rootfssize= < /proc/cmdline | \\
1298 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1299 [ -n "\$size" ] || size="-o size=90%"
1301 mount -t sysfs sysfs /sys
1302 for i in /lib/modules/*.ko ; do
1303 echo -en "Probe \$i \\r"
1304 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1305 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1306 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1307 insmod /lib/modules/\$k.ko 2> /dev/null
1308 done
1309 echo "Loading \$i"
1310 insmod \$i 2> /dev/null
1311 break
1312 done
1313 done
1314 umount /sys
1315 while read var default; do
1316 eval \$var=\$default
1317 getarg \$var \$var
1318 done <<EOT
1319 eth eth0
1320 dns 208.67.222.222,208.67.220.220
1321 netmask 255.255.255.0
1322 gw
1323 ip
1324 EOT
1325 grep -q \$eth /proc/net/dev || sh
1326 if [ -n "\$ip" ]; then
1327 ifconfig \$eth \$ip netmask \$netmask up
1328 route add default gateway \$gw
1329 for i in \$(echo \$dns | sed 's/,/ /g'); do
1330 echo "nameserver \$i" >> /etc/resolv.conf
1331 done
1332 else
1333 udhcpc -f -q -s /lib/udhcpc -i \$eth
1334 fi
1335 for i in $urliso ; do
1336 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1337 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"
1338 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1339 done
1340 getarg urliso URLISO
1341 DIR=fs
1342 if getarg loram DIR; then
1343 DEVICE=\${DIR%,*}
1344 DIR=/\${DIR#*,}
1345 fi
1346 mount -t tmpfs \$size tmpfs /mnt
1347 path2=/mnt/.httpfs/
1348 path=/mnt/.cdrom/
1349 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1350 while [ ! -d \$path/boot ]; do
1351 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1352 httpfs \$i \$path2 && echo \$i && break
1353 done
1354 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1355 done
1357 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1358 umount /proc
1359 branch=:/mnt/.cdrom/\$DIR
1360 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1361 branch=
1362 lp=1
1363 insmod /lib/modules/squashfs.ko 2> /dev/null
1364 for i in \${path}boot/rootfs?.* ; do
1365 fs=\${i#*root}
1366 branch=\$branch:/mnt/.\$fs
1367 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1368 losetup -o 124 /dev/loop\$lp \$i
1369 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1370 lp=\$((\$lp+1))
1371 done
1372 fi
1373 mkdir -p /mnt/.rw/mnt/.httpfs
1374 while read type opt; do
1375 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1376 done <<EOT
1377 aufs br=/mnt/.rw\$branch
1378 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1379 EOT
1380 rm -rf /lib/modules
1381 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1382 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1383 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1384 EOTEOT
1385 chmod +x $TMP_DIR/initfs/init
1386 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1387 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1388 rm -f $i
1389 done 2>/dev/null
1390 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1391 lzma e $TMP_DIR/initfs.gz -si
1392 lzma_set_size $TMP_DIR/initfs.gz
1393 rm -rf $TMP_DIR/initfs
1394 align_to_32bits $TMP_DIR/initfs.gz
1395 return 0
1399 # Move each initramfs to squashfs
1401 build_loram_rootfs() {
1402 rootfs_sizes=""
1403 for i in $TMP_DIR/iso/boot/rootfs*; do
1404 mkdir -p $TMP_DIR/fs
1405 cd $TMP_DIR/fs
1406 uncompress $i | cpio -idm
1407 deduplicate
1408 cd - > /dev/null
1409 rootfs=$TMP_DIR/$(basename $i)
1410 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1411 cd $TMP_DIR
1412 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1413 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1414 rm -f $rootfs
1415 mv $rootfs.cpio $rootfs
1416 cd - > /dev/null
1417 rm -rf $TMP_DIR/fs
1418 done
1422 # Move meta boot configuration files to basic configuration files
1423 # because meta loram flavor is useless when rootfs is not loaded in RAM
1425 unmeta_boot() {
1426 local root=${1:-$TMP_DIR/loramiso}
1427 if [ -f $root/boot/isolinux/noram.cfg ]; then
1428 # We keep enough information to do unloram...
1429 [ -s $root/boot/isolinux/common.cfg ] &&
1430 sed -i 's/label slitaz/label orgslitaz/' \
1431 $root/boot/isolinux/common.cfg
1432 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1433 shift
1434 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1435 $root/boot/isolinux/isolinux.cfg
1436 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1437 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1438 $root/boot/isolinux/*.cfg
1439 fi
1443 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1444 # These squashfs may be loaded in RAM at boot time.
1445 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1446 # Meta flavors are converted to normal flavors.
1448 build_loram_cdrom() {
1449 build_initfs cdrom || return 1
1450 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1451 mkdir $TMP_DIR/loramiso/fs
1452 cd $TMP_DIR/loramiso/fs
1453 for i in $( ls ../boot/root* | sort -r ) ; do
1454 uncompress $i | cpio -idmu
1455 rm -f $i
1456 done
1457 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1458 cd - >/dev/null
1459 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1460 unmeta_boot
1461 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1462 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1463 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1464 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1465 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1466 create_iso $OUTPUT $TMP_DIR/loramiso
1470 # Create http bootstrap to load and remove loram_cdrom
1471 # Meta flavors are converted to normal flavors.
1473 build_loram_http() {
1474 build_initfs http || return 1
1475 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1476 rm -f $TMP_DIR/loramiso/boot/rootfs*
1477 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1478 unmeta_boot
1479 create_iso $OUTPUT $TMP_DIR/loramiso
1483 # Update meta flavor selection sizes.
1484 # Reduce sizes with rootfs gains.
1486 update_metaiso_sizes() {
1487 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1488 do
1489 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1490 local sizes="$rootfs_sizes"
1491 local new
1492 set -- $append
1493 shift
1494 [ "$1" == "ifmem" ] && shift
1495 new=""
1496 while [ -n "$2" ]; do
1497 local s
1498 case "$1" in
1499 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1500 *M) s=$(( ${1%M} * 1024 ));;
1501 *) s=${1%K};;
1502 esac
1503 sizes=${sizes#* }
1504 for i in $sizes ; do
1505 s=$(( $s - $i ))
1506 done
1507 new="$new $s $2"
1508 shift 2
1509 done
1510 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1511 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1512 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1513 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1514 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1515 done
1519 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1520 # Meta flavor selection sizes are updated.
1522 build_loram_ram() {
1523 build_initfs ram || return 1
1524 build_loram_rootfs "$1"
1525 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1526 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1527 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1528 update_metaiso_sizes
1529 create_iso $OUTPUT $TMP_DIR/loramiso
1533 # Remove files installed by packages
1535 find_flavor_rootfs() {
1536 for i in $1/etc/tazlito/*.extract; do
1537 [ -e $i ] || continue
1538 chroot $1 /bin/sh ${i#$1}
1539 done
1541 # Clean hardlinks and files patched by genisofs in /boot
1542 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1543 rm -f $1/boot/$i*
1544 done
1546 # Clean files generated in post_install
1547 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1548 $1/dev/core $1/dev/fd $1/dev/std*
1550 # Verify md5
1551 cat $1$INSTALLED/*/md5sum | \
1552 while read md5 file; do
1553 [ -e "$1$file" ] || continue
1554 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1555 rm -f "$1$file"
1556 done
1558 # Check configuration files
1559 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1560 [ -e $i ] || continue
1561 mkdir /tmp/volatile$$
1562 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1563 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1564 while read file ; do
1565 [ -e "$1/$file" ] || continue
1566 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1567 done
1568 rm -rf /tmp/volatile$$
1569 done
1571 # Remove other files blindly
1572 for i in $1$INSTALLED/*/files.list; do
1573 for file in $(cat "$i"); do
1574 [ "$1$file" -nt "$i" ] && continue
1575 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1576 [ -d "$1$file" ] || rm -f "$1$file"
1577 done
1578 done
1580 # Remove tazpkg files and tmp files
1581 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1582 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1583 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1584 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1585 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1587 # Cleanup directory tree
1588 cd $1
1589 find * -type d | sort -r | while read dir; do
1590 rmdir "$dir" 2>/dev/null
1591 done
1592 cd - > /dev/null
1596 # Get byte(s) from a binary file
1598 get() {
1599 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1603 # Get cpio flavor info from the ISO image
1605 flavordata() {
1606 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1607 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1611 # Restore undigest mirrors
1613 restore_mirrors() {
1614 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1615 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1617 action 'Restoring mirrors...'
1618 if [ -d "$undigest.bak" ]; then
1619 [ -d "$undigest" ] && rm -r "$undigest"
1620 mv "$undigest.bak" "$undigest"
1621 fi
1622 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1623 :; status
1627 # Setup undigest mirrors
1629 setup_mirrors() {
1630 # Setup mirrors in plain system or in chroot (with variable root=)
1631 local mirrorlist="$1" fresh repacked
1632 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1634 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1635 restore_mirrors
1637 _ 'Setting up mirrors for %s...' "$root/"
1638 # Backing up current undigest mirrors and priority
1639 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1640 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1641 rm -rf '/var/www/tazlito/'
1642 mkdir -p '/var/www/tazlito/'
1644 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1645 fresh='/home/slitaz/packages'
1646 if [ -d "$fresh" ]; then
1647 # Setup first undigest mirror
1648 mkdir -p "$undigest/fresh"
1649 echo "$fresh" > "$undigest/fresh/mirror"
1650 echo 'fresh' >> "$priority"
1651 # Rebuild mirror DB if needed
1652 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1653 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1654 tazpkg mkdb "$fresh" --forced --root=''
1655 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1656 fi
1658 # Repacked packages: high priority
1659 repacked="$PACKAGES_REPOSITORY"
1660 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1661 # According to Tazlito setup file (tazlito.conf):
1662 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1663 # or
1664 # WORK_DIR="/home/slitaz"
1665 # and
1666 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1667 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1669 # Setup second undigest mirror
1670 mkdir -p "$undigest/repacked"
1671 echo "$repacked" > "$undigest/repacked/mirror"
1672 echo 'repacked' >> "$priority"
1673 # Rebuild mirror DB if needed
1674 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1675 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1676 tazpkg mkdb "$repacked" --forced --root=''
1677 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1678 fi
1680 # All repositories listed in mirrors list: normal priority
1681 [ -e "$mirrorlist" ] && \
1682 while read mirror; do
1683 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1684 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1685 mkdir -p "$undigest/$mirrorid"
1686 echo "$mirror" > "$undigest/$mirrorid/mirror"
1687 echo "$mirrorid" >> "$priority"
1688 done < "$mirrorlist"
1690 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1692 # Show list of mirrors
1693 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1694 function show(num, name, url) {
1695 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1698 num++;
1699 "cat " db "/undigest/" $0 "/mirror" | getline url;
1700 show(num, $0, url);
1702 END {
1703 num++;
1704 "cat " db "/mirror" | getline url;
1705 show(num, "main", url);
1706 }' "$priority"
1708 tazpkg recharge --quiet >/dev/null
1712 # Get list of 'packages.info' lists using priority
1714 pi_lists() {
1715 local pi
1716 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1717 local priority="$root$LOCALSTATE/priority"
1718 local undigest="$root$LOCALSTATE/undigest"
1721 [ -s "$priority" ] && cat "$priority"
1722 echo 'main'
1723 [ -d "$undigest" ] && ls "$undigest"
1724 } | awk -vun="$undigest/" '
1726 if (arr[$0] != 1) {
1727 arr[$0] = 1;
1728 print un $0 "/packages.info";
1730 }' | sed 's|/undigest/main||' | \
1731 while read pi; do
1732 [ -e "$pi" ] && echo "$pi"
1733 done
1737 # Strip versions from packages list
1739 strip_versions() {
1740 if [ -n "$stripped" ]; then
1741 action 'Consider list %s already stripped' "$(basename "$1")"
1742 status
1743 return 0
1744 fi
1745 action 'Strip versions from list %s...' "$(basename "$1")"
1746 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1747 [ -f "$in_list" ] || die "List '$in_list' not found."
1749 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1750 awk '
1752 if (FILENAME ~ "packages.info") {
1753 # Collect package names
1754 FS = "\t"; pkg[$1] = 1;
1755 } else {
1756 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1757 while (NF > 1 && ! pkg[$0])
1758 NF --;
1759 printf "%s\n", $0;
1761 }' $(pi_lists) "$in_list" > "$tmp_list"
1763 cat "$tmp_list" > "$in_list"
1764 rm "$tmp_list"
1765 status
1769 # Display list of unknown packages (informative)
1771 display_unknown() {
1772 [ -s "$1" ] || return
1773 echo "Unknown packages:" >&2
1774 cat "$1" >&2
1775 rm "$1"
1779 # Display warnings about critical packages absent (informative)
1781 display_warn() {
1782 [ -s "$1" ] || return
1783 echo "Absent critical packages:" >&2
1784 cat "$1" >&2
1785 rm "$1"
1786 echo "Probably ISO image will be unusable."
1790 # Install packages to rootfs
1792 install_list_to_rootfs() {
1793 local list="$1" rootfs="$2" pkg i ii
1794 local undigest="$rootfs/var/lib/tazpkg/undigest"
1796 # initial tazpkg setup in empty rootfs
1797 tazpkg --root=$rootfs >/dev/null 2>&1
1798 # pass current 'mirror' to the rootfs
1799 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1800 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1801 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1802 # link rootfs packages cache to the regular packages cache
1803 rm -r "$rootfs/var/cache/tazpkg"
1804 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1806 setup_mirrors mirrors
1808 # Just in case if flavor doesn't contain "tazlito" package
1809 mkdir -p "$rootfs/etc/tazlito"
1811 newline
1813 # Choose detailed log with --detailed
1814 if [ -n "$detailed" ]; then
1815 while read pkg; do
1816 separator '-'
1817 echo $pkg
1818 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1819 done < $list
1820 separator '='
1821 else
1822 while read pkg; do
1823 action 'Installing package: %s' "$pkg"
1824 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1825 status
1826 done < $list
1827 fi
1828 newline
1830 restore_mirrors
1831 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1832 for i in fresh repacked; do
1833 ii="$undigest/$i"
1834 [ -d "$ii" ] && rm -rf "$ii"
1835 ii="$rootfs/var/lib/tazpkg/priority"
1836 if [ -f "$ii" ]; then
1837 sed -i "/$i/d" "$ii"
1838 [ -s "$ii" ] || rm "$ii"
1839 fi
1840 done
1841 [ -d "$undigest" ] && \
1842 for i in $(find "$undigest" -type f); do
1843 # Remove all undigest PKGDB files but 'mirror'
1844 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1845 done
1846 [ -d "$undigest" ] && \
1847 rmdir --ignore-fail-on-non-empty "$undigest"
1849 # Un-link packages cache
1850 rm "$rootfs/var/cache/tazpkg"
1852 # Clean /var/lib/tazpkg
1853 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1859 ####################
1860 # Tazlito commands #
1861 ####################
1863 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1864 case "$0" in
1865 *reduplicate)
1866 find ${@:-.} ! -type d -links +1 \
1867 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1868 exit 0 ;;
1869 *deduplicate)
1870 deduplicate "$@"
1871 exit 0 ;;
1872 esac
1875 case "$COMMAND" in
1876 stats)
1877 # Tazlito general statistics from the config file.
1879 title 'Tazlito statistics'
1880 optlist "\
1881 Config file : $CONFIG_FILE
1882 ISO name : $ISO_NAME.iso
1883 Volume name : $VOLUM_NAME
1884 Prepared : $PREPARED
1885 Packages repository : $PACKAGES_REPOSITORY
1886 Distro directory : $DISTRO
1887 Additional files : $ADDFILES
1888 " | sed '/: $/d'
1889 footer
1890 ;;
1893 list-addfiles)
1894 # Simple list of additional files in the rootfs
1895 newline
1896 if [ -d "$ADDFILES/rootfs" ]; then
1897 cd $ADDFILES
1898 find rootfs -type f
1899 else
1900 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1901 fi
1902 newline
1903 ;;
1906 gen-config)
1907 # Generate a new config file in the current dir or the specified
1908 # directory by $2.
1910 if [ -n "$2" ]; then
1911 mkdir -p "$2" && cd "$2"
1912 fi
1914 newline
1915 action 'Generating empty tazlito.conf...'
1916 empty_config_file
1917 status
1919 separator
1920 if [ -f 'tazlito.conf' ] ; then
1921 _ 'Configuration file is ready to edit.'
1922 _ 'File location: %s' "$(pwd)/tazlito.conf"
1923 newline
1924 fi
1925 ;;
1928 configure)
1929 # Configure a tazlito.conf config file. Start by getting
1930 # a empty config file and sed it.
1932 if [ -f 'tazlito.conf' ]; then
1933 rm tazlito.conf
1934 else
1935 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1936 'or in the same directory of the file you want to configure.'
1937 cd /etc
1938 fi
1940 empty_config_file
1942 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1944 # ISO name.
1945 echo -n "ISO name : " ; read answer
1946 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1947 # Volume name.
1948 echo -n "Volume name : " ; read answer
1949 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1950 # Packages repository.
1951 echo -n "Packages repository : " ; read answer
1952 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1953 # Distro path.
1954 echo -n "Distro path : " ; read answer
1955 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1956 footer "Config file is ready to use."
1957 echo 'You can now extract an ISO or generate a distro.'
1958 newline
1959 ;;
1962 gen-iso)
1963 # Simply generate a new iso.
1965 check_root
1966 verify_rootcd
1967 gen_livecd_isolinux
1968 distro_stats
1969 ;;
1972 gen-initiso)
1973 # Simply generate a new initramfs with a new iso.
1975 check_root
1976 verify_rootcd
1977 gen_initramfs "$ROOTFS"
1978 gen_livecd_isolinux
1979 distro_stats
1980 ;;
1983 extract-distro)
1984 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1986 check_root
1987 ISO_IMAGE="$2"
1988 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1989 'Example:\n tazlito image.iso /path/target'
1991 # Set the distro path by checking for $3 on cmdline.
1992 TARGET="${3:-$DISTRO}"
1994 # Exit if existing distro is found.
1995 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1996 'Please clean the distro tree or change directory path.'
1998 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2000 # Start to mount the ISO.
2001 action 'Mounting ISO image...'
2002 mkdir -p "$TMP_DIR"
2003 # Get ISO file size.
2004 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2005 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2006 sleep 2
2007 # Prepare target dir, copy the kernel and the rootfs.
2008 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2009 status
2011 action 'Copying the Linux kernel...'
2012 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2013 make_bzImage_hardlink "$TARGET/rootcd/boot"
2014 else
2015 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2016 fi
2017 status
2019 for i in $(ls $TMP_DIR); do
2020 [ "$i" == 'boot' ] && continue
2021 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2022 done
2024 for loader in isolinux syslinux extlinux grub; do
2025 [ -d "$TMP_DIR/boot/$loader" ] || continue
2026 action 'Copying %s files...' "$loader"
2027 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2028 status
2029 done
2031 action 'Copying the rootfs...'
2032 cp $TMP_DIR/boot/rootfs*.?z "$TARGET/rootcd/boot"
2033 status
2035 # Extract initramfs.
2036 cd "$TARGET/rootfs"
2037 action 'Extracting the rootfs...'
2038 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
2039 # unpack /usr
2040 for i in etc/tazlito/*.extract; do
2041 [ -f "$i" ] && . $i ../rootcd
2042 done
2043 # Umount and remove temp directory and cd to $TARGET to get stats.
2044 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2045 cd ..
2046 status
2048 newline
2049 separator
2050 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2051 echo "Distro tree : $(pwd)"
2052 echo "Rootfs size : $(du -sh rootfs)"
2053 echo "Rootcd size : $(du -sh rootcd)"
2054 footer
2055 ;;
2058 list-flavors)
2059 # Show available flavors.
2060 list='/etc/tazlito/flavors.list'
2061 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2062 title 'List of flavors'
2063 cat $list
2064 footer
2065 ;;
2068 show-flavor)
2069 # Show flavor descriptions.
2070 set -e
2071 flavor=${2%.flavor}
2072 flv_dir="$(extract_flavor "$flavor")"
2073 desc="$flv_dir/$flavor.desc"
2074 if [ -n "$brief" ]; then
2075 if [ -z "$noheader" ]; then
2076 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2077 separator
2078 fi
2079 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2080 "$(field ISO "$desc")" \
2081 "$(field Rootfs "$desc")" \
2082 "$(field Description "$desc")"
2083 else
2084 separator
2085 cat "$desc"
2086 fi
2087 cleanup
2088 ;;
2091 gen-liveflavor)
2092 # Generate a new flavor from the live system.
2093 FLAVOR=${2%.flavor}
2094 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2096 case "$FLAVOR" in
2097 -?|-h*|--help)
2098 cat <<EOT
2099 SliTaz Live Tool - Version: $VERSION
2101 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2103 $(boldify '<flavor-patch-file> format:')
2104 $(optlist "\
2105 code data
2106 + package to add
2107 - package to remove
2108 ! non-free package to add
2109 ? display message
2110 @ flavor description
2111 ")
2113 $(boldify 'Example:')
2114 $(optlist "\
2115 @ Developer tools for SliTaz maintainers
2116 + slitaz-toolchain
2117 + mercurial
2118 ")
2119 EOT
2120 exit 1
2121 ;;
2122 esac
2123 mv /etc/tazlito/distro-packages.list \
2124 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2125 rm -f distro-packages.list non-free.list 2>/dev/null
2126 tazpkg recharge
2128 DESC=""
2129 [ -n "$3" ] && \
2130 while read action pkg; do
2131 case "$action" in
2132 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2133 -) yes | tazpkg remove $pkg ;;
2134 !) echo $pkg >> non-free.list ;;
2135 @) DESC="$pkg" ;;
2136 \?) echo -en "$pkg"; read action ;;
2137 esac
2138 done < $3
2140 yes '' | tazlito gen-distro
2141 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2142 mv /etc/tazlito/distro-packages.list.$$ \
2143 /etc/tazlito/distro-packages.list 2>/dev/null
2144 ;;
2147 gen-flavor)
2148 # Generate a new flavor from the last ISO image generated
2149 FLAVOR=${2%.flavor}
2150 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2152 title 'Flavor generation'
2153 check_rootfs
2154 FILES="$FLAVOR.pkglist"
2156 action 'Creating file %s...' "$FLAVOR.flavor"
2157 for i in rootcd rootfs; do
2158 if [ -d "$ADDFILES/$i" ] ; then
2159 FILES="$FILES\n$FLAVOR.$i"
2160 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2161 fi
2162 done
2163 status
2165 answer=$(grep -s ^Description $FLAVOR.desc)
2166 answer=${answer#Description : }
2167 if [ -z "$answer" ]; then
2168 echo -n "Description: "
2169 read answer
2170 fi
2172 action 'Compressing flavor %s...' "$FLAVOR"
2173 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2174 echo "Description : $answer" >> $FLAVOR.desc
2175 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2176 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2177 for i in $(ls $ROOTFS$INSTALLED); do
2178 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2179 EXTRAVERSION=""
2180 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2181 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2182 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2183 echo "$i" >> $FLAVOR.nonfree
2184 else
2185 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2186 fi
2187 done
2188 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2189 for i in $LOCALSTATE/undigest/*/mirror ; do
2190 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2191 done
2192 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2193 touch -t 197001010100.00 $FLAVOR.*
2194 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2195 rm $(echo -e $FILES)
2196 status
2198 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2199 ;;
2202 upgrade-flavor)
2203 # Strip versions from pkglist and update estimated numbers in flavor.desc
2204 flavor="${2%.flavor}"
2205 set -e
2206 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2207 set +e
2209 flv_dir="$(extract_flavor "$flavor")"
2211 strip_versions "$flv_dir/$flavor.pkglist"
2213 action 'Updating %s...' "$flavor.desc"
2215 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2216 set -- $(module calc_sizes "$flv_dir" "$flavor")
2217 restore_mirrors >/dev/null
2219 sed -i -e '/Image is ready/d' \
2220 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2221 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2222 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2223 -e "s|\(Packages *:\).*$|\1 $4|" \
2224 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2225 "$flv_dir/$flavor.desc"
2227 pack_flavor "$flv_dir" "$flavor"
2228 status
2229 display_unknown "$flv_dir/err"
2230 display_warn "$flv_dir/warn"
2231 cleanup
2232 ;;
2235 extract-flavor)
2236 # Extract a flavor into $FLAVORS_REPOSITORY
2237 flavor="${2%.flavor}"
2238 set -e
2239 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2240 set +e
2242 action 'Extracting %s...' "$flavor.flavor"
2243 flv_dir="$(extract_flavor "$flavor" full)"
2244 storage="$FLAVORS_REPOSITORY/$flavor"
2246 rm -rf "$storage" 2>/dev/null
2247 mkdir -p "$storage"
2248 cp -a "$flv_dir"/* "$storage"
2249 rm "$storage/description"
2250 status
2252 strip_versions "$storage/packages.list"
2254 cleanup
2255 ;;
2258 pack-flavor)
2259 # Create a flavor from $FLAVORS_REPOSITORY.
2260 flavor=${2%.flavor}
2261 storage="$FLAVORS_REPOSITORY/$flavor"
2263 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2265 action 'Creating flavor %s...' "$flavor"
2266 tmp_dir="$(mktemp -d)"
2268 while read from to; do
2269 [ -s "$storage/$from" ] || continue
2270 cp -a "$storage/$from" "$tmp_dir/$to"
2271 done <<EOT
2272 mirrors $flavor.mirrors
2273 distro.sh $flavor-distro.sh
2274 receipt $flavor.receipt
2275 non-free.list $flavor.nonfree
2276 EOT
2278 # Build the package list.
2279 # It can include a list from another flavor with the keyword @include
2280 if [ -s "$storage/packages.list" ]; then
2281 include=$(grep '^@include' "$storage/packages.list")
2282 if [ -n "$include" ]; then
2283 include=${include#@include }
2284 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2285 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2286 else
2287 echo -e "\nERROR: Can't find include package list from $include\n"
2288 fi
2289 fi
2290 # Generate the final/initial package list
2291 [ -s "$storage/packages.list" ] && \
2292 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2293 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2294 fi
2296 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2297 # Process multi-rootfs flavor
2298 . "$storage/receipt"
2299 set -- $ROOTFS_SELECTION
2300 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2301 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2302 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2304 for i in rootcd rootfs; do
2305 mkdir "$tmp_dir/$i"
2306 # Copy extra files from the first flavor
2307 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2308 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2309 # Overload extra files by meta flavor
2310 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2311 [ -n "$(ls $tmp_dir/$i)" ] &&
2312 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2313 dogzip "$tmp_dir/$flavor.$i"
2314 rm -rf "$tmp_dir/$i"
2315 done
2316 else
2317 # Process plain flavor
2318 for i in rootcd rootfs; do
2319 [ -d "$storage/$i" ] || continue
2320 (cd "$storage/$i";
2321 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2322 done
2323 fi
2325 unset VERSION MAINTAINER ROOTFS_SELECTION
2326 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2327 ROOTFS_SIZE="$1 (estimated)"
2328 INITRAMFS_SIZE="$2 (estimated)"
2329 ISO_SIZE="$3 (estimated)"
2330 PKGNUM="$4"
2331 . "$storage/receipt"
2333 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2334 Flavor : $FLAVOR
2335 Description : $SHORT_DESC
2336 Version : $VERSION
2337 Maintainer : $MAINTAINER
2338 LiveCD RAM size : $FRUGAL_RAM
2339 Rootfs list : $ROOTFS_SELECTION
2340 Build date : $(date '+%Y%m%d at %T')
2341 Packages : $PKGNUM
2342 Rootfs size : $ROOTFS_SIZE
2343 Initramfs size : $INITRAMFS_SIZE
2344 ISO image size : $ISO_SIZE
2345 ================================================================================
2347 EOT
2349 rm -f $tmp_dir/packages.list
2350 pack_flavor "$tmp_dir" "$flavor"
2351 status
2352 display_unknown "$tmp_dir/err"
2353 display_warn "$flv_dir/warn"
2354 cleanup
2355 ;;
2358 get-flavor)
2359 # Get a flavor's files and prepare for gen-distro.
2360 flavor=${2%.flavor}
2361 title 'Preparing %s distro flavor' "$flavor"
2362 set -e
2363 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2364 set +e
2366 action 'Cleaning %s...' "$DISTRO"
2367 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2368 # Clean old files
2369 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2370 [ -f "$i" ] && rm "$i"
2371 done
2372 mkdir -p "$DISTRO"
2373 status
2375 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2377 action 'Extracting flavor %s...' "$flavor.flavor"
2378 flv_dir="$(extract_flavor "$flavor" info)"
2379 cp -a "$flv_dir"/* .
2380 mv packages.list distro-packages.list
2381 mv -f info /etc/tazlito
2382 status
2384 for i in rootcd rootfs; do
2385 if [ -d "$i" ]; then
2386 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2387 fi
2388 done
2390 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2391 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2393 action 'Updating %s...' 'tazlito.conf'
2394 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2395 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2396 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2397 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2398 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2399 status
2401 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2402 cleanup
2403 ;;
2406 iso2flavor)
2407 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2408 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2410 FLAVOR=${3%.flavor}
2411 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2412 mount -o loop,ro $2 $TMP_DIR/iso
2413 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2414 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2415 ! -s $TMP_DIR/flavor/*.desc ]; then
2416 _ 'META flavors are not supported.'
2417 umount -d $TMP_DIR/iso
2418 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2419 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2420 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2421 umount -d $TMP_DIR/iso
2422 else
2423 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2424 uncompress $i | \
2425 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2426 done
2427 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2428 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2429 '/etc/slitaz-release' '/boot/rootfs.gz'
2430 umount -d $TMP_DIR/iso
2431 else
2432 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2433 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2434 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2435 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2436 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2437 umount -d $TMP_DIR/iso
2438 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2439 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2440 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2441 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2442 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2443 < $TMP_DIR/rootfs$INSTALLED.md5
2444 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2445 if [ -s $TMP_DIR/flavor/*desc ]; then
2446 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2447 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2448 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2449 for i in rootfs rootcd ; do
2450 [ -s $TMP_DIR/flavor/*.list$i ] &&
2451 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2452 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2453 done
2454 else
2455 find_flavor_rootfs $TMP_DIR/rootfs
2456 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2457 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2458 for i in rootfs rootcd ; do
2459 [ "$(ls $TMP_DIR/$i)" ] &&
2460 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2461 done
2462 unset VERSION MAINTAINER
2463 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2464 if [ -n "$DESCRIPTION" ]; then
2465 _n 'Flavor version : '; read -t 30 VERSION
2466 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2467 fi
2469 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2470 Flavor : $FLAVOR
2471 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2472 Version : ${VERSION:-1.0}
2473 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2474 LiveCD RAM size : $RAM_SIZE
2475 Build date : $BUILD_DATE
2476 Packages : $PKGCNT
2477 Rootfs size : $ROOTFS_SIZE
2478 Initramfs size : $INITRAMFS_SIZE
2479 ISO image size : $ISO_SIZE
2480 ================================================================================
2482 EOT
2483 longline "Tazlito can't detect each file installed during \
2484 a package post_install. You should extract this flavor (tazlito extract-flavor \
2485 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2486 tree and remove files generated by post_installs.
2487 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2488 repack the flavor (tazlito pack-flavor $FLAVOR)"
2489 fi
2490 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2491 fi
2492 fi
2493 rm -rf $TMP_DIR
2494 ;;
2497 gen-distro)
2498 # Generate a live distro tree with a set of packages.
2500 check_root
2501 start_time=$(date +%s)
2503 # Tazlito options: --iso or --cdrom
2504 CDROM=''
2505 [ -n "$iso" ] && CDROM="-o loop $iso"
2506 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2508 # Check if a package list was specified on cmdline.
2509 if [ -f "$2" ]; then
2510 LIST_NAME="$2"
2511 else
2512 LIST_NAME='distro-packages.list'
2513 fi
2515 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2516 'Please clean the distro tree or change directory path.'
2517 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2518 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2520 # If list not given: build list with all installed packages
2521 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2522 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2523 fi
2525 # Exit if no list name.
2526 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2528 # Start generation.
2529 title 'Tazlito generating a distro'
2531 # Misc checks
2532 mkdir -p "$PACKAGES_REPOSITORY"
2533 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2534 newline
2536 # Mount CD-ROM to be able to repack boot-loader packages
2537 if [ ! -e /boot -a -n "$CDROM" ]; then
2538 mkdir $TMP_MNT
2539 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2540 ln -s "$TMP_MNT/boot" /
2541 if [ ! -d "$ADDFILES/rootcd" ] ; then
2542 mkdir -p "$ADDFILES/rootcd"
2543 for i in $(ls $TMP_MNT); do
2544 [ "$i" == 'boot' ] && continue
2545 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2546 done
2547 fi
2548 else
2549 rmdir "$TMP_MNT"
2550 fi
2551 fi
2553 # Rootfs stuff.
2554 echo 'Preparing the rootfs directory...'
2555 mkdir -p "$ROOTFS"
2556 export root="$ROOTFS"
2557 # pass current 'mirror' to the root
2558 mkdir -p $root/var/lib/tazpkg $root/etc
2559 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2560 cp -f /etc/slitaz-release $root/etc/slitaz-release
2561 strip_versions "$LIST_NAME"
2563 if [ "$REPACK" == 'y' ]; then
2564 # Determine full packages list with all dependencies
2565 tmp_dir="$(mktemp -d)"
2566 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2567 touch "$tmp_dir/full.pkglist"
2568 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2570 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2571 while read pkgname pkgver; do
2572 # Is package in full list?
2573 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2574 # Is package already repacked?
2575 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2576 _ 'Repacking %s...' "$pkgname-$pkgver"
2577 tazpkg repack "$pkgname" --quiet
2578 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2579 status
2580 done
2582 rm -r "$tmp_dir"
2583 fi
2585 if [ -f non-free.list ]; then
2586 # FIXME: working in the ROOTFS chroot?
2587 newline
2588 echo 'Preparing non-free packages...'
2589 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2590 for pkg in $(cat 'non-free.list'); do
2591 if [ ! -d "$INSTALLED/$pkg" ]; then
2592 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2593 tazpkg get-install get-$pkg
2594 fi
2595 get-$pkg "$ROOTFS"
2596 fi
2597 tazpkg repack $pkg
2598 pkg=$(ls $pkg*.tazpkg)
2599 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2600 mv $pkg $PACKAGES_REPOSITORY
2601 done
2602 fi
2603 cp $LIST_NAME $DISTRO/distro-packages.list
2604 newline
2606 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2608 cd $DISTRO
2609 cp distro-packages.list $ROOTFS/etc/tazlito
2610 # Copy all files from $ADDFILES/rootfs to the rootfs.
2611 if [ -d "$ADDFILES/rootfs" ] ; then
2612 action 'Copying addfiles content to the rootfs...'
2613 cp -a $ADDFILES/rootfs/* $ROOTFS
2614 status
2615 fi
2617 action 'Root filesystem is generated...'; status
2619 # Root CD part.
2620 action 'Preparing the rootcd directory...'
2621 mkdir -p $ROOTCD
2622 status
2624 # Move the boot dir with the Linux kernel from rootfs.
2625 # The efi & boot dirs go directly on the CD.
2626 if [ -d "$ROOTFS/efi" ] ; then
2627 action 'Moving the efi directory...'
2628 mv $ROOTFS/efi $ROOTCD
2629 status
2630 fi
2631 if [ -d "$ROOTFS/boot" ] ; then
2632 action 'Moving the boot directory...'
2633 mv $ROOTFS/boot $ROOTCD
2634 status
2635 fi
2636 cd $DISTRO
2637 # Copy all files from $ADDFILES/rootcd to the rootcd.
2638 if [ -d "$ADDFILES/rootcd" ] ; then
2639 action 'Copying addfiles content to the rootcd...'
2640 cp -a $ADDFILES/rootcd/* $ROOTCD
2641 status
2642 fi
2643 # Execute the distro script used to perform tasks in the rootfs
2644 # before compression. Give rootfs path in arg
2645 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2646 if [ -x "$DISTRO_SCRIPT" ]; then
2647 echo 'Executing distro script...'
2648 sh $DISTRO_SCRIPT $DISTRO
2649 fi
2651 # Execute the custom_rules() found in receipt.
2652 if [ -s "$TOP_DIR/receipt" ]; then
2653 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2654 echo -e "Executing: custom_rules()\n"
2655 . "$TOP_DIR/receipt"
2656 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2657 fi
2658 fi
2660 # Multi-rootfs
2661 if [ -s /etc/tazlito/rootfs.list ]; then
2663 FLAVOR_LIST="$(awk '{
2664 for (i = 2; i <= NF; i+=2)
2665 printf "%s ", $i;
2666 }' /etc/tazlito/rootfs.list)"
2668 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2669 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2670 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2672 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2673 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2674 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2675 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2677 n=0
2678 last=$ROOTFS
2679 while read flavor; do
2680 n=$(($n+1))
2681 mkdir ${ROOTFS}0$n
2682 export root="${ROOTFS}0$n"
2683 # initial tazpkg setup in empty rootfs
2684 tazpkg --root=$root >/dev/null 2>&1
2686 newline
2687 boldify "Building $flavor rootfs..."
2689 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2690 cp "$TOP_DIR/$flavor.flavor" .
2692 if [ ! -s "$flavor.flavor" ]; then
2693 # We may have it in $FLAVORS_REPOSITORY
2694 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2695 tazlito pack-flavor $flavor
2696 else
2697 download $flavor.flavor
2698 fi
2699 fi
2701 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2702 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2703 cp $flavor.pkglist $DISTRO/list-packages0$n
2704 status
2706 strip_versions "$DISTRO/list-packages0$n"
2708 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2710 action 'Updating the boot directory...'
2711 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD
2712 rm -rf ${ROOTFS}0$n/boot
2714 cd $DISTRO
2715 if [ -s $flavor.rootfs ]; then
2716 _n 'Adding %s rootfs extra files...' "$flavor"
2717 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2718 fi
2720 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2721 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2722 status
2724 rm -f $flavor.flavor install-list
2725 mergefs ${ROOTFS}0$n $last
2726 last=${ROOTFS}0$n
2727 done <<EOT
2728 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2729 EOT
2730 #'
2731 i=$(($n+1))
2732 while [ $n -gt 0 ]; do
2733 mv ${ROOTFS}0$n ${ROOTFS}$i
2734 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2735 gen_initramfs ${ROOTFS}$i
2736 n=$(($n-1))
2737 i=$(($i-1))
2738 export LZMA_HISTORY_BITS=26
2739 done
2740 mv $ROOTFS ${ROOTFS}$i
2741 gen_initramfs ${ROOTFS}$i
2742 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2743 ROOTFS=${ROOTFS}1
2744 else
2745 # Initramfs and ISO image stuff.
2746 gen_initramfs $ROOTFS
2747 fi
2748 gen_livecd_isolinux
2749 distro_stats
2750 cleanup
2751 ;;
2754 clean-distro)
2755 # Remove old distro tree.
2757 check_root
2758 title 'Cleaning: %s' "$DISTRO"
2759 if [ -d "$DISTRO" ] ; then
2760 if [ -d "$ROOTFS" ] ; then
2761 action 'Removing the rootfs...'
2762 rm -f $DISTRO/$INITRAMFS
2763 rm -rf $ROOTFS
2764 status
2765 fi
2766 if [ -d "$ROOTCD" ] ; then
2767 action 'Removing the rootcd...'
2768 rm -rf $ROOTCD
2769 status
2770 fi
2771 action 'Removing eventual ISO image...'
2772 rm -f $DISTRO/$ISO_NAME.iso
2773 rm -f $DISTRO/$ISO_NAME.md5
2774 status
2775 fi
2776 footer
2777 ;;
2780 check-distro)
2781 # Check for a few LiveCD needed files not installed by packages.
2783 # TODO: Remove this function.
2784 # First two files are maintained by tazpkg while it runs on rootfs,
2785 # while last one file should be maintained by tazlito itself.
2786 check_rootfs
2787 title 'Checking distro: %s' "$ROOTFS"
2788 # SliTaz release info.
2789 rel='/etc/slitaz-release'
2790 if [ ! -f "$ROOTFS$rel" ]; then
2791 _ 'Missing release info: %s' "$rel"
2792 else
2793 action 'Release : %s' "$(cat $ROOTFS$rel)"
2794 status
2795 fi
2796 # Tazpkg mirror.
2797 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2798 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2799 todomsg
2800 else
2801 action 'Mirror configuration exists...'
2802 status
2803 fi
2804 # Isolinux msg
2805 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2806 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2807 todomsg
2808 else
2809 action 'Isolinux message seems good...'
2810 status
2811 fi
2812 footer
2813 ;;
2816 writeiso)
2817 # Writefs to ISO image including /home unlike gen-distro we don't use
2818 # packages to generate a rootfs, we build a compressed rootfs with all
2819 # the current filesystem similar to 'tazusb writefs'.
2821 DISTRO='/home/slitaz/distro'
2822 ROOTCD="$DISTRO/rootcd"
2823 COMPRESSION="${2:-none}"
2824 ISO_NAME="${3:-slitaz}"
2825 check_root
2826 # Start info
2827 title 'Write filesystem to ISO'
2828 longline "The command writeiso will write the current filesystem into a \
2829 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2830 newline
2831 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2833 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2834 # Save some space
2835 rm -rf /var/cache/tazpkg/*
2836 rm -f /var/lib/tazpkg/*.bak
2837 rm -rf $DISTRO
2839 # Optionally remove sound card selection and screen resolution.
2840 if [ -z $LaunchedByTazpanel ]; then
2841 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2842 case $anser in
2843 y)
2844 action 'Removing current sound card and screen configurations...'
2845 rm -f /var/lib/sound-card-driver
2846 rm -f /var/lib/alsa/asound.state
2847 rm -f /etc/X11/xorg.conf ;;
2848 *)
2849 action 'Keeping current sound card and screen configurations...' ;;
2850 esac
2851 status
2852 newline
2854 # Optionally remove i18n settings
2855 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2856 case $anser in
2857 y)
2858 action 'Removing current locale/keymap settings...'
2859 newline > /etc/locale.conf
2860 newline > /etc/keymap.conf ;;
2861 *)
2862 action 'Keeping current locale/keymap settings...' ;;
2863 esac
2864 status
2865 fi
2867 # Clean-up files by default
2868 newline > /etc/udev/rules.d/70-persistent-net.rules
2869 newline > /etc/udev/rules.d/70-persistant-cd.rules
2871 # Create list of files including default user files since it is defined in /etc/passwd
2872 # and some new users might have been added.
2873 cd /
2874 echo 'init' > /tmp/list
2875 for dir in bin etc sbin var dev lib root usr home opt; do
2876 [ -d $dir ] && find $dir
2877 done >> /tmp/list
2879 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2880 [ -d $dir ] && echo $dir
2881 done >> /tmp/list
2883 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2885 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2886 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2887 #fi
2888 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2889 touch /var/log/wtmp
2891 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2892 sed -i "/var\/log\/$removelog/d" /tmp/list
2893 done
2895 # Generate initramfs with specified compression and display rootfs
2896 # size in realtime.
2897 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2899 write_initramfs &
2900 sleep 2
2901 cd - > /dev/null
2902 echo -en "\nFilesystem size:"
2903 while [ ! -f /tmp/rootfs ]; do
2904 sleep 1
2905 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2906 done
2907 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2908 echo -e "\n"
2909 rm -f /tmp/rootfs
2911 # Move freshly generated rootfs to the cdrom.
2912 mkdir -p $ROOTCD/boot
2913 mv -f /$INITRAMFS $ROOTCD/boot
2914 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2916 # Now we need the kernel and isolinux files.
2917 copy_from_cd() {
2918 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2919 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2920 unmeta_boot $ROOTCD
2921 umount /media/cdrom
2924 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2925 copy_from_cd;
2926 elif mount | grep /media/cdrom; then
2927 copy_from_cd;
2928 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2929 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2930 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2931 else
2932 touch /tmp/.write-iso-error
2933 longline "When SliTaz is running in RAM the kernel and bootloader \
2934 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2935 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2936 echo -en "----\nENTER to continue..."; read i
2937 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2938 copy_from_cd
2939 fi
2941 # Generate the iso image.
2942 touch /tmp/.write-iso
2943 newline
2944 cd $DISTRO
2945 create_iso $ISO_NAME.iso $ROOTCD
2946 action 'Creating the ISO md5sum...'
2947 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2948 status
2950 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2951 rm -f /tmp/.write-iso
2953 if [ -z $LaunchedByTazpanel ]; then
2954 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2955 case $anser in
2956 y)
2957 umount /dev/cdrom 2>/dev/null
2958 eject
2959 echo -n "Please insert a blank CD-ROM and press ENTER..."
2960 read i && sleep 2
2961 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2962 echo -en "----\nENTER to continue..."; read i ;;
2963 *)
2964 exit 0 ;;
2965 esac
2966 fi
2967 ;;
2970 burn-iso)
2971 # Guess CD-ROM device, ask user and burn the ISO.
2973 check_root
2974 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2975 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2976 # We can specify an alternative ISO from the cmdline.
2977 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2978 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2980 title 'Tazlito burn ISO'
2981 echo "CD-ROM device : /dev/$DRIVE_NAME"
2982 echo "Drive speed : $DRIVE_SPEED"
2983 echo "ISO image : $iso"
2984 footer
2986 case $(yesorno 'Burn ISO image?' 'n') in
2987 y)
2988 title 'Starting Wodim to burn the ISO...'
2989 sleep 2
2990 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2991 footer 'ISO image is burned to CD-ROM.'
2992 ;;
2993 *)
2994 die 'Exiting. No ISO burned.'
2995 ;;
2996 esac
2997 ;;
3000 merge)
3001 # Merge multiple rootfs into one iso.
3003 if [ -z "$2" ]; then
3004 cat <<EOT
3005 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3007 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3008 i.e: rootfsN is a subset of rootfsN-1
3009 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3010 The boot loader will select the rootfs according to the RAM size detected.
3012 Example:
3013 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3015 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3016 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3018 EOT
3019 exit 2
3020 fi
3022 shift # skip merge
3023 append="$1 slitaz1"
3024 shift # skip size1
3025 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3027 ISO=$1.merged
3029 # Extract filesystems
3030 action 'Mounting %s' "$1"
3031 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3032 status || cleanup_merge
3034 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3035 make_bzImage_hardlink $TMP_DIR/iso/boot
3036 umount -d $TMP_DIR/mnt
3037 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3038 _ '%s is already a merged iso. Aborting.' "$1"
3039 cleanup_merge
3040 fi
3041 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3042 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3043 if [ ! -f /boot/isolinux/ifmem.c32 -a
3044 ! -f /boot/isolinux/c32box.c32 ]; then
3045 cat <<EOT
3046 No file /boot/isolinux/ifmem.c32
3047 Please install syslinux package !
3048 EOT
3049 rm -rf $TMP_DIR
3050 exit 1
3051 fi
3052 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3053 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3054 fi
3056 action 'Extracting %s' 'iso/rootfs.gz'
3057 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3058 [ -d $TMP_DIR/rootfs1/etc ]
3059 status || cleanup_merge
3061 n=1
3062 while [ -n "$2" ]; do
3063 shift # skip rootfs N-1
3064 p=$n
3065 n=$(($n + 1))
3066 append="$append $1 slitaz$n"
3067 shift # skip size N
3068 mkdir -p $TMP_DIR/rootfs$n
3070 action 'Extracting %s' "$1"
3071 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3072 [ -d "$TMP_DIR/rootfs$n/etc" ]
3073 status || cleanup_merge
3075 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3076 action 'Creating %s' "rootfs$p.gz"
3077 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3078 status
3079 done
3080 action 'Creating %s' "rootfs$n.gz"
3081 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3082 status
3083 rm -f $TMP_DIR/iso/boot/rootfs.gz
3084 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3085 create_iso $ISO $TMP_DIR/iso
3086 rm -rf $TMP_DIR
3087 ;;
3090 repack)
3091 # Repack an iso with maximum lzma compression ratio.
3093 ISO=$2
3094 mkdir -p $TMP_DIR/mnt
3096 # Extract filesystems
3097 action 'Mounting %s' "$ISO"
3098 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3099 status || cleanup_merge
3101 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3102 umount -d $TMP_DIR/mnt
3104 for i in $TMP_DIR/iso/boot/rootfs* ; do
3105 action 'Repacking %s' "$(basename $i)"
3106 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3107 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3108 align_to_32bits $i
3109 status
3110 done
3112 create_iso $ISO $TMP_DIR/iso
3113 rm -rf $TMP_DIR
3114 ;;
3117 build-loram)
3118 # Build a Live CD for low RAM systems.
3120 ISO="$2"
3121 OUTPUT="$3"
3122 [ -z "$3" ] && \
3123 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3124 mkdir -p "$TMP_DIR/iso"
3125 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3126 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3127 if ! check_iso_for_loram ; then
3128 umount -d "$TMP_DIR/iso"
3129 die "$ISO is not a valid SliTaz live CD. Abort."
3130 fi
3131 case "$4" in
3132 cdrom) build_loram_cdrom ;;
3133 http) build_loram_http ;;
3134 *) build_loram_ram "$5" ;;
3135 esac
3136 umount $TMP_DIR/iso # no -d: needs /proc
3137 losetup -d $loopdev
3138 rm -rf $TMP_DIR
3139 ;;
3142 emu-iso)
3143 # Emulate an ISO image with Qemu.
3144 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3145 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3146 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3147 echo -e "\nStarting Qemu emulator:\n"
3148 echo -e "qemu $QEMU_OPTS $iso\n"
3149 qemu $QEMU_OPTS $iso
3150 ;;
3153 deduplicate)
3154 # Deduplicate files in a tree
3155 shift
3156 deduplicate "$@"
3157 ;;
3160 usage|*)
3161 # Print usage also for all unknown commands.
3162 usage
3163 ;;
3164 esac
3166 exit 0