tazlito view tazlito @ rev 478

uefi support aventually... (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jan 20 11:22:45 2018 +0100 (2018-01-20)
parents 7959015b775d
children 0eed66d92e2a
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 make_bzImage_hardlink $2/boot
518 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
520 cat > /tmp/cdsort$$ <<EOT
521 $PWD/boot/isolinux 100
522 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
523 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
524 $(find $PWD/efi -type f 2>/dev/null | awk 'BEGIN{n=299} { print $1 " " n-- }')
525 $PWD/boot/isolinux/efi.img 300
526 $PWD/boot/isolinux/isolinux.bin 399
527 $PWD/boot/isolinux/boot.cat 400
528 EOT
530 action 'Computing md5...'
531 touch boot/isolinux/boot.cat
532 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; > md5sum
533 status
535 cd - >/dev/null
536 title 'Generating ISO image'
538 _ 'Generating %s' "$1"
539 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
540 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
541 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
542 -no-emul-boot -boot-load-size 4 -boot-info-table \
543 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
544 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
545 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
546 -A "tazlito $VERSION/$(genisoimage --version)" \
547 -copyright README -P "www.slitaz.org" -no-pad $2
548 rm -f /tmp/cdsort$$
549 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
551 mkdir /tmp/mnt$$
552 mount -o loop,ro $1 /tmp/mnt$$
553 fixup_uefi_part $1 /tmp/mnt$$
554 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
555 ${uefi:+boot/isolinux/efi.img} ; do
556 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
557 done
558 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
559 seek=$(stat -m /tmp/mnt$$/md5sum | sed q) 2> /dev/null
560 umount -d /tmp/mnt$$
561 rmdir /tmp/mnt$$
563 if [ -s '/etc/tazlito/info' ]; then
564 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
565 action 'Storing ISO info...'
566 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
567 status
568 fi
569 fi
571 if [ -x '/usr/bin/isohybrid' ]; then
572 action 'Creating hybrid ISO...'
573 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
574 status
575 fi
577 if [ -x '/usr/bin/iso2exe' ]; then
578 echo 'Creating EXE header...'
579 /usr/bin/iso2exe $1 2>/dev/null
580 fi
581 }
584 # Generate a new ISO image using isolinux.
586 gen_livecd_isolinux() {
587 # Some packages may want to alter iso
588 genisohooks iso
589 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
591 # Set date for boot msg.
592 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
593 DATE=$(date +%Y%m%d)
594 action 'Setting build date to: %s...' "$DATE"
595 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
596 status
597 fi
599 cd $DISTRO
600 create_iso $ISO_NAME.iso $ROOTCD
602 action 'Creating the ISO md5sum...'
603 md5sum $ISO_NAME.iso > $ISO_NAME.md5
604 status
606 separator
607 # Some packages may want to alter final iso
608 genisohooks final
609 }
612 lzma_history_bits() {
613 #
614 # This generates an ISO which boots with Qemu but gives
615 # rootfs errors in frugal or liveUSB mode.
616 #
617 # local n
618 # local sz
619 # n=20 # 1Mb
620 # sz=$(du -sk $1 | cut -f1)
621 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
622 # n=$(( $n + 1 ))
623 # sz=$(( $sz / 2 ))
624 # done
625 # echo $n
626 echo ${LZMA_HISTORY_BITS:-24}
627 }
630 lzma_switches() {
631 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
632 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
633 }
636 lzma_set_size() {
637 # Update size field for lzma'd file packed using -si switch
638 return # Need to fix kernel code?
640 local n i
641 n=$(unlzma < $1 | wc -c)
642 for i in $(seq 1 8); do
643 printf '\\\\x%02X' $(($n & 255))
644 n=$(($n >> 8))
645 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
646 }
649 align_to_32bits() {
650 local size=$(stat -c %s ${1:-/dev/null})
651 [ $((${size:-0} & 3)) -ne 0 ] &&
652 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
653 }
656 dogzip() {
657 gzip -9 > $1
658 [ -x /usr/bin/advdef ] && advdef -qz4 $1
659 }
662 # Pack rootfs
664 pack_rootfs() {
665 ( cd $1; find . -print | cpio -o -H newc ) | \
666 case "$COMPRESSION" in
667 none)
668 _ 'Creating %s without compression...' 'initramfs'
669 cat > $2
670 ;;
671 gzip)
672 _ 'Creating %s with gzip compression...' 'initramfs'
673 dogzip $2
674 ;;
675 *)
676 _ 'Creating %s with lzma compression...' 'initramfs'
677 lzma e -si -so $(lzma_switches $1) > $2
678 lzma_set_size $2
679 ;;
680 esac
681 align_to_32bits $2
682 echo 1 > /tmp/rootfs
683 }
686 # Compression functions for writeiso.
688 write_initramfs() {
689 case "$COMPRESSION" in
690 lzma)
691 _n 'Creating %s with lzma compression...' "$INITRAMFS"
692 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
693 align='y'
694 lzma_set_size "/$INITRAMFS"
695 ;;
696 gzip)
697 _ 'Creating %s with gzip compression...' "$INITRAMFS"
698 cpio -o -H newc | dogzip "/$INITRAMFS"
699 ;;
700 *)
701 # align='y'
702 _ 'Creating %s without compression...' "$INITRAMFS"
703 cpio -o -H newc > "/$INITRAMFS"
704 ;;
705 esac < /tmp/list
706 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
707 echo 1 > /tmp/rootfs
708 }
711 # Deduplicate files (MUST be on the same filesystem).
713 deduplicate() {
714 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
715 (
716 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
717 while read attr inode link file; do
718 [ -L "$file" ] && continue
719 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
720 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
721 rm -f "$file"
722 if ln "$old_file" "$file" 2>/dev/null; then
723 inode="$old_inode"
724 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
725 save="$(($save+(${attr%%-*}+512)/1024))"
726 else
727 cp -a "$old_file" "$file"
728 fi
729 fi
730 fi
731 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
732 done
733 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
734 )
736 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
737 (
738 old_attr=""; hardlinks=0;
739 while read attr inode link file; do
740 attr="${attr/-TARGET-/-$(readlink $file)}"
741 if [ "$attr" == "$old_attr" ]; then
742 if [ "$inode" != "$old_inode" ]; then
743 rm -f "$file"
744 if ln "$old_file" "$file" 2>/dev/null; then
745 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
746 else
747 cp -a "$old_file" "$file"
748 fi
749 fi
750 else
751 old_file="$file"
752 old_attr="$attr"
753 old_inode="$inode"
754 fi
755 done
756 _ '%s duplicate symlinks.' "$hardlinks"
757 )
758 }
761 # Generate a new initramfs from the root filesystem.
763 gen_initramfs() {
764 # Just in case CTRL+c
765 rm -f $DISTRO/gen
767 # Some packages may want to alter rootfs
768 genisohooks rootfs
769 cd $1
771 # Normalize file time
772 find $1 -newer $1 -exec touch -hr $1 {} \;
774 # Link duplicate files
775 deduplicate
777 # Use lzma if installed. Display rootfs size in realtime.
778 rm -f /tmp/rootfs 2>/dev/null
779 pack_rootfs . $DISTRO/$(basename $1).gz &
780 sleep 2
781 echo -en "\nFilesystem size:"
782 while [ ! -f /tmp/rootfs ]; do
783 sleep 1
784 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
785 done
786 echo -e "\n"
787 rm -f /tmp/rootfs
788 cd $DISTRO
789 mv $(basename $1).gz $ROOTCD/boot
790 }
793 distro_sizes() {
794 if [ -n "$start_time" ]; then
795 time=$(($(date +%s) - $start_time))
796 sec=$time
797 div=$(( ($time + 30) / 60))
798 [ "$div" -ne 0 ] && min="~ ${div}m"
799 _ 'Build time : %ss %s' "$sec" "$min"
800 fi
801 cat <<EOT
802 Build date : $(date +%Y%m%d)
803 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
804 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
805 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
806 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
807 EOT
808 footer "Image is ready: $ISO_NAME.iso"
809 }
812 # Print ISO and rootfs size.
814 distro_stats() {
815 title 'Distro statistics: %s' "$DISTRO"
816 distro_sizes
817 }
820 # Create an empty configuration file.
822 empty_config_file() {
823 cat >> tazlito.conf <<"EOF"
824 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
825 #
827 # Name of the ISO image to generate.
828 ISO_NAME=""
830 # ISO image volume name.
831 VOLUM_NAME="SliTaz"
833 # Name of the preparer.
834 PREPARED="$USER"
836 # Path to the packages repository and the packages.list.
837 PACKAGES_REPOSITORY=""
839 # Path to the distro tree to gen-distro from a list of packages.
840 DISTRO=""
842 # Path to the directory containing additional files
843 # to copy into the rootfs and rootcd of the LiveCD.
844 ADDFILES="$DISTRO/addfiles"
846 # Default answer for binary question (Y or N)
847 DEFAULT_ANSWER="ASK"
849 # Compression utility (lzma, gzip or none)
850 COMPRESSION="lzma"
851 EOF
852 }
855 # Extract rootfs.gz somewhere
857 extract_rootfs() {
858 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
859 # First part (lzcat or zcat) may not fail, but cpio will fail on uncorrect format
860 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
861 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
862 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
863 }
866 # Extract flavor file to temp directory
868 extract_flavor() {
869 # Input: $1 - flavor name to extract;
870 # $2 = absent/empty: just extract 'outer layer'
871 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
872 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
873 # Output: temp dir path where flavor was extracted
874 local f="$1.flavor" from to infos="$1.desc"
875 [ -f "$f" ] || die "File '$f' not found"
876 local dir="$(mktemp -d)"
877 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
879 if [ -n "$2" ]; then
880 cd $dir
882 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
884 for i in rootcd rootfs; do
885 [ -f "$1.$i" ] || continue
886 mkdir "$i"
887 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
888 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
889 rm "$1.$i"
890 done
891 touch -t 197001010100.00 "$1.*"
892 # Info to be stored inside ISO
893 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
894 rm $1.list*
896 # Renames
897 while read from to; do
898 [ -f "$from" ] || continue
899 mv "$from" "$to"
900 done <<EOT
901 $1.nonfree non-free.list
902 $1.pkglist packages.list
903 $1-distro.sh distro.sh
904 $1.receipt receipt
905 $1.mirrors mirrors
906 $1.desc description
907 EOT
908 fi
910 echo $dir
911 }
914 # Pack flavor file from temp directory
916 pack_flavor() {
917 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
918 }
921 # Remove duplicate files
923 files_match() {
924 if [ -d "$1" ]; then
925 return 1
927 elif [ -L "$1" ] && [ -L "$2" ]; then
928 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
930 elif [ -f "$1" ] && [ -f "$2" ]; then
931 cmp -s "$1" "$2" && return 0
933 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
934 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
935 return 0
937 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
938 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
939 return 0
941 fi
942 return 1
943 }
945 remove_with_path() {
946 dir="$(dirname $1)"
947 rm -f "$1"
948 while rmdir "$dir" 2> /dev/null; do
949 dir="$(dirname $dir)"
950 done
951 }
953 mergefs() {
954 # Note, many packages have files with spaces in the name
955 IFS=$'\n'
957 local size1=$(du -hs "$1" | awk '{ print $1 }')
958 local size2=$(du -hs "$2" | awk '{ print $1 }')
959 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
961 # merge symlinks files and devices
962 ( cd "$1"; find ) | \
963 while read file; do
964 files_match "$1/$file" "$2/$file" "$file" &&
965 remove_with_path "$2/$file"
966 done
968 unset IFS
969 status
970 }
973 cleanup_merge() {
974 rm -rf $TMP_DIR
975 exit 1
976 }
979 # Update isolinux config files for multiple rootfs
981 update_bootconfig() {
982 local files
983 action 'Updating boot config files...'
984 files="$(grep -l 'include common' $1/*.cfg)"
985 for file in $files; do
986 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
987 if (/label/) label=$0;
988 else if (/kernel/) kernel=$0;
989 else if (/append/) {
990 i=index($0,"rootfs.gz");
991 append=substr($0,i+9);
992 }
993 else if (/include/) {
994 for (i = 1; i <= n; i++) {
995 print label i
996 print kernel;
997 initrd="initrd=/boot/rootfs" n ".gz"
998 for (j = n - 1; j >= i; j--) {
999 initrd=initrd ",/boot/rootfs" j ".gz";
1001 printf "\tappend %s%s\n",initrd,append;
1002 print "";
1004 print;
1006 else print;
1007 }' < $file > $file.$$
1008 mv -f $file.$$ $file
1009 done
1010 sel="$(echo $2 | awk '{
1011 for (i=1; i<=NF; i++)
1012 if (i % 2 == 0) printf " slitaz%d", i/2
1013 else printf " %s", $i
1014 }')"
1016 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1018 label slitaz
1019 kernel /boot/isolinux/ifmem.c32
1020 append$sel noram
1022 label noram
1023 config noram.cfg
1025 EOT
1027 # Update vesamenu
1028 if [ -s "$1/isolinux.cfg" ]; then
1029 files="$files $1/isolinux.cfg"
1030 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1031 BEGIN {
1032 kernel = " COM32 c32box.c32"
1035 if (/ROWS/) print "MENU ROWS " n+$3;
1036 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1037 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1038 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1039 else if (/VSHIFT/) {
1040 x = $3-n;
1041 if (x < 0) x = 0;
1042 print "MENU VSHIFT " x;
1044 else if (/rootfs.gz/) {
1045 linux = "";
1046 if (/bzImage/) linux = "linux /boot/bzImage ";
1047 i = index($0, "rootfs.gz");
1048 append = substr($0, i+9);
1049 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1050 printf "\tappend%s noram\n", sel;
1051 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1052 for (i = 1; i <= n; i++) {
1053 print "LABEL slitaz" i
1054 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1055 printf "%s\n", kernel;
1056 initrd = "initrd=/boot/rootfs" n ".gz"
1057 for (j = n - 1; j >= i; j--) {
1058 initrd = initrd ",/boot/rootfs" j ".gz";
1060 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1063 else if (/bzImage/) kernel = $0;
1064 else print;
1065 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1066 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1067 fi
1069 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1070 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1071 cat > $1/noram.cfg <<EOT
1072 implicit 0
1073 prompt 1
1074 timeout 80
1075 $(grep '^F[0-9]' $1/isolinux.cfg)
1077 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1078 say Not enough RAM to boot slitaz. Trying hacker mode...
1079 default hacker
1080 label hacker
1081 KERNEL /boot/bzImage
1082 append rw root=/dev/null vga=normal
1084 label reboot
1085 EOT
1087 if [ -s $1/c32box.c32 ]; then
1088 cat >> $1/noram.cfg <<EOT
1089 COM32 c32box.c32
1090 append reboot
1092 label poweroff
1093 COM32 c32box.c32
1094 append poweroff
1096 EOT
1097 else
1098 echo " com32 reboot.c32" >> $1/noram.cfg
1099 fi
1101 # Restore real label names
1102 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1103 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1104 while read pat; do
1105 sed -i "s/slitaz$pat/" $files
1106 done
1107 status
1111 # Uncompress rootfs or module to stdout
1113 uncompress() {
1114 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1115 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1119 # Install a missing package
1121 install_package() {
1122 if [ -z "$2" ]; then
1123 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1124 else
1125 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1126 fi
1127 case "$answer" in
1128 y)
1129 # We don't want package on host cache.
1130 action 'Getting and installing package: %s' "$1"
1131 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1132 status ;;
1133 *)
1134 return 1 ;;
1135 esac
1139 # Check iso for loram transformation
1141 check_iso_for_loram() {
1142 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1143 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1147 # Build initial rootfs for loram ISO ram/cdrom/http
1149 build_initfs() {
1150 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1151 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1152 mirror3.slitaz.org mirror.slitaz.org"
1153 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1154 [ -z "$version" ] && die "Can't find the kernel version." \
1155 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1157 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1158 need_lib=false
1159 for i in bin dev run mnt proc tmp sys lib/modules; do
1160 mkdir -p $TMP_DIR/initfs/$i
1161 done
1162 ln -s bin $TMP_DIR/initfs/sbin
1163 ln -s . $TMP_DIR/initfs/usr
1164 for aufs in aufs overlayfs; do
1165 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1166 install_package $aufs $version && break
1167 done || return 1
1168 [ -s /init ] || install_package slitaz-boot-scripts
1169 cp /init $TMP_DIR/initfs/
1170 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1171 $TMP_DIR/initfs/lib/modules
1172 if [ "$1" == 'cdrom' ]; then
1173 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1174 else
1175 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1176 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1177 install_package linux-squashfs $version || return 1
1178 done
1179 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1180 $TMP_DIR/initfs/lib/modules
1181 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1182 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1183 fi
1184 if [ "$1" == 'http' ]; then
1185 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1186 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1187 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1188 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1189 cp -a /dev/fuse $TMP_DIR/initfs/dev
1190 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1191 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1192 else
1193 need_lib=true
1194 fi
1195 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1196 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1197 else
1198 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1199 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1200 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1201 cp -a /lib/librt* $TMP_DIR/initfs/lib
1202 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1203 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1204 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1205 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1206 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1207 need_lib=true
1208 fi
1209 cd $TMP_DIR/fs
1210 echo 'Getting slitaz-release & ethernet modules...'
1211 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1212 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1213 [ -s rootfs* ] || continue
1214 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1215 rm -f rootfs*
1216 done 2>&1 > /dev/null
1217 cd - > /dev/null
1218 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1219 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1220 -type f -name '*.ko*' | while read mod; do
1221 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1222 uncompress $mod > $f
1223 grep -q alias=pci: $f || rm -f $f
1224 done
1225 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1226 f=$(basename $i)..z
1227 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1228 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1229 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1230 for j in $deps; do
1231 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1232 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1233 done
1234 done
1235 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"
1236 _n 'List of URLs to insert: '
1237 read -t 30 urliso2
1238 urliso="$urliso2 $urliso"
1239 fi
1240 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1241 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1242 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1243 else
1244 cp /bin/busybox $TMP_DIR/initfs/bin
1245 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1246 cp /sbin/insmod $TMP_DIR/initfs/bin
1247 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1248 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1249 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1250 fi
1251 need_lib=true
1252 fi
1253 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1254 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1255 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1256 done
1257 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1258 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1259 $TMP_DIR/initfs/lib/modules 2>/dev/null
1260 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1261 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1262 cp -a $i $TMP_DIR/initfs/dev
1263 done
1264 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1265 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1266 cp -a $i $TMP_DIR/initfs/dev
1267 done 2>/dev/null
1268 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1269 cp -a $i $TMP_DIR/initfs/lib
1270 done
1271 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1272 #!/bin/sh
1274 getarg() {
1275 grep -q " \$1=" /proc/cmdline || return 1
1276 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1277 return 0
1280 copy_rootfs() {
1281 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1282 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1283 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1284 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1285 path=/mnt/
1286 return 0
1287 else
1288 rm -f /mnt/rootfs*
1289 return 1
1290 fi
1293 echo "Switching / to tmpfs..."
1294 mount -t proc proc /proc
1295 size="\$(grep rootfssize= < /proc/cmdline | \\
1296 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1297 [ -n "\$size" ] || size="-o size=90%"
1299 mount -t sysfs sysfs /sys
1300 for i in /lib/modules/*.ko ; do
1301 echo -en "Probe \$i \\r"
1302 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1303 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1304 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1305 insmod /lib/modules/\$k.ko 2> /dev/null
1306 done
1307 echo "Loading \$i"
1308 insmod \$i 2> /dev/null
1309 break
1310 done
1311 done
1312 umount /sys
1313 while read var default; do
1314 eval \$var=\$default
1315 getarg \$var \$var
1316 done <<EOT
1317 eth eth0
1318 dns 208.67.222.222,208.67.220.220
1319 netmask 255.255.255.0
1320 gw
1321 ip
1322 EOT
1323 grep -q \$eth /proc/net/dev || sh
1324 if [ -n "\$ip" ]; then
1325 ifconfig \$eth \$ip netmask \$netmask up
1326 route add default gateway \$gw
1327 for i in \$(echo \$dns | sed 's/,/ /g'); do
1328 echo "nameserver \$i" >> /etc/resolv.conf
1329 done
1330 else
1331 udhcpc -f -q -s /lib/udhcpc -i \$eth
1332 fi
1333 for i in $urliso ; do
1334 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1335 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"
1336 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1337 done
1338 getarg urliso URLISO
1339 DIR=fs
1340 if getarg loram DIR; then
1341 DEVICE=\${DIR%,*}
1342 DIR=/\${DIR#*,}
1343 fi
1344 mount -t tmpfs \$size tmpfs /mnt
1345 path2=/mnt/.httpfs/
1346 path=/mnt/.cdrom/
1347 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1348 while [ ! -d \$path/boot ]; do
1349 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1350 httpfs \$i \$path2 && echo \$i && break
1351 done
1352 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1353 done
1355 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1356 umount /proc
1357 branch=:/mnt/.cdrom/\$DIR
1358 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1359 branch=
1360 lp=1
1361 insmod /lib/modules/squashfs.ko 2> /dev/null
1362 for i in \${path}boot/rootfs?.* ; do
1363 fs=\${i#*root}
1364 branch=\$branch:/mnt/.\$fs
1365 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1366 losetup -o 124 /dev/loop\$lp \$i
1367 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1368 lp=\$((\$lp+1))
1369 done
1370 fi
1371 mkdir -p /mnt/.rw/mnt/.httpfs
1372 while read type opt; do
1373 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1374 done <<EOT
1375 aufs br=/mnt/.rw\$branch
1376 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1377 EOT
1378 rm -rf /lib/modules
1379 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1380 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1381 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1382 EOTEOT
1383 chmod +x $TMP_DIR/initfs/init
1384 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1385 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1386 rm -f $i
1387 done 2>/dev/null
1388 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1389 lzma e $TMP_DIR/initfs.gz -si
1390 lzma_set_size $TMP_DIR/initfs.gz
1391 rm -rf $TMP_DIR/initfs
1392 align_to_32bits $TMP_DIR/initfs.gz
1393 return 0
1397 # Move each initramfs to squashfs
1399 build_loram_rootfs() {
1400 rootfs_sizes=""
1401 for i in $TMP_DIR/iso/boot/rootfs*; do
1402 mkdir -p $TMP_DIR/fs
1403 cd $TMP_DIR/fs
1404 uncompress $i | cpio -idm
1405 deduplicate
1406 cd - > /dev/null
1407 rootfs=$TMP_DIR/$(basename $i)
1408 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1409 cd $TMP_DIR
1410 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1411 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1412 rm -f $rootfs
1413 mv $rootfs.cpio $rootfs
1414 cd - > /dev/null
1415 rm -rf $TMP_DIR/fs
1416 done
1420 # Move meta boot configuration files to basic configuration files
1421 # because meta loram flavor is useless when rootfs is not loaded in RAM
1423 unmeta_boot() {
1424 local root=${1:-$TMP_DIR/loramiso}
1425 if [ -f $root/boot/isolinux/noram.cfg ]; then
1426 # We keep enough information to do unloram...
1427 [ -s $root/boot/isolinux/common.cfg ] &&
1428 sed -i 's/label slitaz/label orgslitaz/' \
1429 $root/boot/isolinux/common.cfg
1430 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1431 shift
1432 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1433 $root/boot/isolinux/isolinux.cfg
1434 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1435 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1436 $root/boot/isolinux/*.cfg
1437 fi
1441 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1442 # These squashfs may be loaded in RAM at boot time.
1443 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1444 # Meta flavors are converted to normal flavors.
1446 build_loram_cdrom() {
1447 build_initfs cdrom || return 1
1448 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1449 mkdir $TMP_DIR/loramiso/fs
1450 cd $TMP_DIR/loramiso/fs
1451 for i in $( ls ../boot/root* | sort -r ) ; do
1452 uncompress $i | cpio -idmu
1453 rm -f $i
1454 done
1455 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1456 cd - >/dev/null
1457 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1458 unmeta_boot
1459 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1460 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1461 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1462 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1463 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1464 create_iso $OUTPUT $TMP_DIR/loramiso
1468 # Create http bootstrap to load and remove loram_cdrom
1469 # Meta flavors are converted to normal flavors.
1471 build_loram_http() {
1472 build_initfs http || return 1
1473 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1474 rm -f $TMP_DIR/loramiso/boot/rootfs*
1475 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1476 unmeta_boot
1477 create_iso $OUTPUT $TMP_DIR/loramiso
1481 # Update meta flavor selection sizes.
1482 # Reduce sizes with rootfs gains.
1484 update_metaiso_sizes() {
1485 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1486 do
1487 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1488 local sizes="$rootfs_sizes"
1489 local new
1490 set -- $append
1491 shift
1492 [ "$1" == "ifmem" ] && shift
1493 new=""
1494 while [ -n "$2" ]; do
1495 local s
1496 case "$1" in
1497 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1498 *M) s=$(( ${1%M} * 1024 ));;
1499 *) s=${1%K};;
1500 esac
1501 sizes=${sizes#* }
1502 for i in $sizes ; do
1503 s=$(( $s - $i ))
1504 done
1505 new="$new $s $2"
1506 shift 2
1507 done
1508 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1509 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1510 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1511 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1512 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1513 done
1517 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1518 # Meta flavor selection sizes are updated.
1520 build_loram_ram() {
1521 build_initfs ram || return 1
1522 build_loram_rootfs "$1"
1523 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1524 make_bzImage_hardlink $TMP_DIR/loramiso/boot
1525 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1526 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1527 update_metaiso_sizes
1528 create_iso $OUTPUT $TMP_DIR/loramiso
1532 # Remove files installed by packages
1534 find_flavor_rootfs() {
1535 for i in $1/etc/tazlito/*.extract; do
1536 [ -e $i ] || continue
1537 chroot $1 /bin/sh ${i#$1}
1538 done
1540 # Clean hardlinks and files patched by genisofs in /boot
1541 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1542 rm -f $1/boot/$i*
1543 done
1545 # Clean files generated in post_install
1546 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1547 $1/dev/core $1/dev/fd $1/dev/std*
1549 # Verify md5
1550 cat $1$INSTALLED/*/md5sum | \
1551 while read md5 file; do
1552 [ -e "$1$file" ] || continue
1553 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1554 rm -f "$1$file"
1555 done
1557 # Check configuration files
1558 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1559 [ -e $i ] || continue
1560 mkdir /tmp/volatile$$
1561 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1562 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1563 while read file ; do
1564 [ -e "$1/$file" ] || continue
1565 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1566 done
1567 rm -rf /tmp/volatile$$
1568 done
1570 # Remove other files blindly
1571 for i in $1$INSTALLED/*/files.list; do
1572 for file in $(cat "$i"); do
1573 [ "$1$file" -nt "$i" ] && continue
1574 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1575 [ -d "$1$file" ] || rm -f "$1$file"
1576 done
1577 done
1579 # Remove tazpkg files and tmp files
1580 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1581 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1582 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1583 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1584 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1586 # Cleanup directory tree
1587 cd $1
1588 find * -type d | sort -r | while read dir; do
1589 rmdir "$dir" 2>/dev/null
1590 done
1591 cd - > /dev/null
1595 # Get byte(s) from a binary file
1597 get() {
1598 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null
1602 # Get cpio flavor info from the ISO image
1604 flavordata() {
1605 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1606 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1610 # Restore undigest mirrors
1612 restore_mirrors() {
1613 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1614 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1616 action 'Restoring mirrors...'
1617 if [ -d "$undigest.bak" ]; then
1618 [ -d "$undigest" ] && rm -r "$undigest"
1619 mv "$undigest.bak" "$undigest"
1620 fi
1621 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1622 :; status
1626 # Setup undigest mirrors
1628 setup_mirrors() {
1629 # Setup mirrors in plain system or in chroot (with variable root=)
1630 local mirrorlist="$1" fresh repacked
1631 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1633 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1634 restore_mirrors
1636 _ 'Setting up mirrors for %s...' "$root/"
1637 # Backing up current undigest mirrors and priority
1638 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1639 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1640 rm -rf '/var/www/tazlito/'
1641 mkdir -p '/var/www/tazlito/'
1643 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1644 fresh='/home/slitaz/packages'
1645 if [ -d "$fresh" ]; then
1646 # Setup first undigest mirror
1647 mkdir -p "$undigest/fresh"
1648 echo "$fresh" > "$undigest/fresh/mirror"
1649 echo 'fresh' >> "$priority"
1650 # Rebuild mirror DB if needed
1651 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1652 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1653 tazpkg mkdb "$fresh" --forced --root=''
1654 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1655 fi
1657 # Repacked packages: high priority
1658 repacked="$PACKAGES_REPOSITORY"
1659 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1660 # According to Tazlito setup file (tazlito.conf):
1661 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1662 # or
1663 # WORK_DIR="/home/slitaz"
1664 # and
1665 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1666 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1668 # Setup second undigest mirror
1669 mkdir -p "$undigest/repacked"
1670 echo "$repacked" > "$undigest/repacked/mirror"
1671 echo 'repacked' >> "$priority"
1672 # Rebuild mirror DB if needed
1673 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1674 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1675 tazpkg mkdb "$repacked" --forced --root=''
1676 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1677 fi
1679 # All repositories listed in mirrors list: normal priority
1680 [ -e "$mirrorlist" ] && \
1681 while read mirror; do
1682 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1683 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1684 mkdir -p "$undigest/$mirrorid"
1685 echo "$mirror" > "$undigest/$mirrorid/mirror"
1686 echo "$mirrorid" >> "$priority"
1687 done < "$mirrorlist"
1689 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1691 # Show list of mirrors
1692 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1693 function show(num, name, url) {
1694 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1697 num++;
1698 "cat " db "/undigest/" $0 "/mirror" | getline url;
1699 show(num, $0, url);
1701 END {
1702 num++;
1703 "cat " db "/mirror" | getline url;
1704 show(num, "main", url);
1705 }' "$priority"
1707 tazpkg recharge --quiet >/dev/null
1711 # Get list of 'packages.info' lists using priority
1713 pi_lists() {
1714 local pi
1715 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1716 local priority="$root$LOCALSTATE/priority"
1717 local undigest="$root$LOCALSTATE/undigest"
1720 [ -s "$priority" ] && cat "$priority"
1721 echo 'main'
1722 [ -d "$undigest" ] && ls "$undigest"
1723 } | awk -vun="$undigest/" '
1725 if (arr[$0] != 1) {
1726 arr[$0] = 1;
1727 print un $0 "/packages.info";
1729 }' | sed 's|/undigest/main||' | \
1730 while read pi; do
1731 [ -e "$pi" ] && echo "$pi"
1732 done
1736 # Strip versions from packages list
1738 strip_versions() {
1739 if [ -n "$stripped" ]; then
1740 action 'Consider list %s already stripped' "$(basename "$1")"
1741 status
1742 return 0
1743 fi
1744 action 'Strip versions from list %s...' "$(basename "$1")"
1745 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1746 [ -f "$in_list" ] || die "List '$in_list' not found."
1748 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1749 awk '
1751 if (FILENAME ~ "packages.info") {
1752 # Collect package names
1753 FS = "\t"; pkg[$1] = 1;
1754 } else {
1755 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1756 while (NF > 1 && ! pkg[$0])
1757 NF --;
1758 printf "%s\n", $0;
1760 }' $(pi_lists) "$in_list" > "$tmp_list"
1762 cat "$tmp_list" > "$in_list"
1763 rm "$tmp_list"
1764 status
1768 # Display list of unknown packages (informative)
1770 display_unknown() {
1771 [ -s "$1" ] || return
1772 echo "Unknown packages:" >&2
1773 cat "$1" >&2
1774 rm "$1"
1778 # Display warnings about critical packages absent (informative)
1780 display_warn() {
1781 [ -s "$1" ] || return
1782 echo "Absent critical packages:" >&2
1783 cat "$1" >&2
1784 rm "$1"
1785 echo "Probably ISO image will be unusable."
1789 # Install packages to rootfs
1791 install_list_to_rootfs() {
1792 local list="$1" rootfs="$2" pkg i ii
1793 local undigest="$rootfs/var/lib/tazpkg/undigest"
1795 # initial tazpkg setup in empty rootfs
1796 tazpkg --root=$rootfs >/dev/null 2>&1
1797 # pass current 'mirror' to the rootfs
1798 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1799 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1800 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1801 # link rootfs packages cache to the regular packages cache
1802 rm -r "$rootfs/var/cache/tazpkg"
1803 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1805 setup_mirrors mirrors
1807 # Just in case if flavor not contains "tazlito" package
1808 mkdir -p "$rootfs/etc/tazlito"
1810 newline
1812 # Choose detailed log with --detailed
1813 if [ -n "$detailed" ]; then
1814 while read pkg; do
1815 separator '-'
1816 echo $pkg
1817 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1818 done < $list
1819 separator '='
1820 else
1821 while read pkg; do
1822 action 'Installing package: %s' "$pkg"
1823 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1824 status
1825 done < $list
1826 fi
1827 newline
1829 restore_mirrors
1830 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1831 for i in fresh repacked; do
1832 ii="$undigest/$i"
1833 [ -d "$ii" ] && rm -rf "$ii"
1834 ii="$rootfs/var/lib/tazpkg/priority"
1835 if [ -f "$ii" ]; then
1836 sed -i "/$i/d" "$ii"
1837 [ -s "$ii" ] || rm "$ii"
1838 fi
1839 done
1840 [ -d "$undigest" ] && \
1841 for i in $(find "$undigest" -type f); do
1842 # Remove all undigest PKGDB files but 'mirror'
1843 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1844 done
1845 [ -d "$undigest" ] && \
1846 rmdir --ignore-fail-on-non-empty "$undigest"
1848 # Un-link packages cache
1849 rm "$rootfs/var/cache/tazpkg"
1851 # Clean /var/lib/tazpkg
1852 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1858 ####################
1859 # Tazlito commands #
1860 ####################
1862 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1863 case "$0" in
1864 *reduplicate)
1865 find ${@:-.} ! -type d -links +1 \
1866 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1867 exit 0 ;;
1868 *deduplicate)
1869 deduplicate "$@"
1870 exit 0 ;;
1871 esac
1874 case "$COMMAND" in
1875 stats)
1876 # Tazlito general statistics from the config file.
1878 title 'Tazlito statistics'
1879 optlist "\
1880 Config file : $CONFIG_FILE
1881 ISO name : $ISO_NAME.iso
1882 Volume name : $VOLUM_NAME
1883 Prepared : $PREPARED
1884 Packages repository : $PACKAGES_REPOSITORY
1885 Distro directory : $DISTRO
1886 Additional files : $ADDFILES
1887 " | sed '/: $/d'
1888 footer
1889 ;;
1892 list-addfiles)
1893 # Simple list of additional files in the rootfs
1894 newline
1895 if [ -d "$ADDFILES/rootfs" ]; then
1896 cd $ADDFILES
1897 find rootfs -type f
1898 else
1899 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1900 fi
1901 newline
1902 ;;
1905 gen-config)
1906 # Generate a new config file in the current dir or the specified
1907 # directory by $2.
1909 if [ -n "$2" ]; then
1910 mkdir -p "$2" && cd "$2"
1911 fi
1913 newline
1914 action 'Generating empty tazlito.conf...'
1915 empty_config_file
1916 status
1918 separator
1919 if [ -f 'tazlito.conf' ] ; then
1920 _ 'Configuration file is ready to edit.'
1921 _ 'File location: %s' "$(pwd)/tazlito.conf"
1922 newline
1923 fi
1924 ;;
1927 configure)
1928 # Configure a tazlito.conf config file. Start by getting
1929 # a empty config file and sed it.
1931 if [ -f 'tazlito.conf' ]; then
1932 rm tazlito.conf
1933 else
1934 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1935 'or in the same directory of the file you want to configure.'
1936 cd /etc
1937 fi
1939 empty_config_file
1941 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1943 # ISO name.
1944 echo -n "ISO name : " ; read answer
1945 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1946 # Volume name.
1947 echo -n "Volume name : " ; read answer
1948 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
1949 # Packages repository.
1950 echo -n "Packages repository : " ; read answer
1951 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
1952 # Distro path.
1953 echo -n "Distro path : " ; read answer
1954 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
1955 footer "Config file is ready to use."
1956 echo 'You can now extract an ISO or generate a distro.'
1957 newline
1958 ;;
1961 gen-iso)
1962 # Simply generate a new iso.
1964 check_root
1965 verify_rootcd
1966 gen_livecd_isolinux
1967 distro_stats
1968 ;;
1971 gen-initiso)
1972 # Simply generate a new initramfs with a new iso.
1974 check_root
1975 verify_rootcd
1976 gen_initramfs "$ROOTFS"
1977 gen_livecd_isolinux
1978 distro_stats
1979 ;;
1982 extract-distro)
1983 # Extract an ISO image to a directory and rebuild the LiveCD tree.
1985 check_root
1986 ISO_IMAGE="$2"
1987 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
1988 'Example:\n tazlito image.iso /path/target'
1990 # Set the distro path by checking for $3 on cmdline.
1991 TARGET="${3:-$DISTRO}"
1993 # Exit if existing distro is found.
1994 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
1995 'Please clean the distro tree or change directory path.'
1997 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
1999 # Start to mount the ISO.
2000 action 'Mounting ISO image...'
2001 mkdir -p "$TMP_DIR"
2002 # Get ISO file size.
2003 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2004 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2005 sleep 2
2006 # Prepare target dir, copy the kernel and the rootfs.
2007 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2008 status
2010 action 'Copying the Linux kernel...'
2011 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2012 make_bzImage_hardlink "$TARGET/rootcd/boot"
2013 else
2014 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2015 fi
2016 status
2018 for i in $(ls $TMP_DIR); do
2019 [ "$i" == 'boot' ] && continue
2020 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2021 done
2023 for loader in isolinux syslinux extlinux grub; do
2024 [ -d "$TMP_DIR/boot/$loader" ] || continue
2025 action 'Copying %s files...' "$loader"
2026 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2027 status
2028 done
2030 action 'Copying the rootfs...'
2031 cp $TMP_DIR/boot/rootfs*.?z "$TARGET/rootcd/boot"
2032 status
2034 # Extract initramfs.
2035 cd "$TARGET/rootfs"
2036 action 'Extracting the rootfs...'
2037 extract_rootfs "$TARGET/rootcd/boot/$INITRAMFS" "$TARGET/rootfs"
2038 # unpack /usr
2039 for i in etc/tazlito/*.extract; do
2040 [ -f "$i" ] && . $i ../rootcd
2041 done
2042 # Umount and remove temp directory and cd to $TARGET to get stats.
2043 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2044 cd ..
2045 status
2047 newline
2048 separator
2049 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2050 echo "Distro tree : $(pwd)"
2051 echo "Rootfs size : $(du -sh rootfs)"
2052 echo "Rootcd size : $(du -sh rootcd)"
2053 footer
2054 ;;
2057 list-flavors)
2058 # Show available flavors.
2059 list='/etc/tazlito/flavors.list'
2060 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2061 title 'List of flavors'
2062 cat $list
2063 footer
2064 ;;
2067 show-flavor)
2068 # Show flavor description.
2069 set -e
2070 flavor=${2%.flavor}
2071 flv_dir="$(extract_flavor "$flavor")"
2072 desc="$flv_dir/$flavor.desc"
2073 if [ -n "$brief" ]; then
2074 if [ -z "$noheader" ]; then
2075 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2076 separator
2077 fi
2078 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2079 "$(field ISO "$desc")" \
2080 "$(field Rootfs "$desc")" \
2081 "$(field Description "$desc")"
2082 else
2083 separator
2084 cat "$desc"
2085 fi
2086 cleanup
2087 ;;
2090 gen-liveflavor)
2091 # Generate a new flavor from the live system.
2092 FLAVOR=${2%.flavor}
2093 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2095 case "$FLAVOR" in
2096 -?|-h*|--help)
2097 cat <<EOT
2098 SliTaz Live Tool - Version: $VERSION
2100 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2102 $(boldify '<flavor-patch-file> format:')
2103 $(optlist "\
2104 code data
2105 + package to add
2106 - package to remove
2107 ! non-free package to add
2108 ? display message
2109 @ flavor description
2110 ")
2112 $(boldify 'Example:')
2113 $(optlist "\
2114 @ Developer tools for SliTaz maintainers
2115 + slitaz-toolchain
2116 + mercurial
2117 ")
2118 EOT
2119 exit 1
2120 ;;
2121 esac
2122 mv /etc/tazlito/distro-packages.list \
2123 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2124 rm -f distro-packages.list non-free.list 2>/dev/null
2125 tazpkg recharge
2127 DESC=""
2128 [ -n "$3" ] && \
2129 while read action pkg; do
2130 case "$action" in
2131 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2132 -) yes | tazpkg remove $pkg ;;
2133 !) echo $pkg >> non-free.list ;;
2134 @) DESC="$pkg" ;;
2135 \?) echo -en "$pkg"; read action ;;
2136 esac
2137 done < $3
2139 yes '' | tazlito gen-distro
2140 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2141 mv /etc/tazlito/distro-packages.list.$$ \
2142 /etc/tazlito/distro-packages.list 2>/dev/null
2143 ;;
2146 gen-flavor)
2147 # Generate a new flavor from the last ISO image generated
2148 FLAVOR=${2%.flavor}
2149 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2151 title 'Flavor generation'
2152 check_rootfs
2153 FILES="$FLAVOR.pkglist"
2155 action 'Creating file %s...' "$FLAVOR.flavor"
2156 for i in rootcd rootfs; do
2157 if [ -d "$ADDFILES/$i" ] ; then
2158 FILES="$FILES\n$FLAVOR.$i"
2159 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2160 fi
2161 done
2162 status
2164 answer=$(grep -s ^Description $FLAVOR.desc)
2165 answer=${answer#Description : }
2166 if [ -z "$answer" ]; then
2167 echo -n "Description: "
2168 read answer
2169 fi
2171 action 'Compressing flavor %s...' "$FLAVOR"
2172 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2173 echo "Description : $answer" >> $FLAVOR.desc
2174 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2175 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2176 for i in $(ls $ROOTFS$INSTALLED); do
2177 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2178 EXTRAVERSION=""
2179 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2180 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2181 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2182 echo "$i" >> $FLAVOR.nonfree
2183 else
2184 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2185 fi
2186 done
2187 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2188 for i in $LOCALSTATE/undigest/*/mirror ; do
2189 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2190 done
2191 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2192 touch -t 197001010100.00 $FLAVOR.*
2193 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2194 rm $(echo -e $FILES)
2195 status
2197 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2198 ;;
2201 upgrade-flavor)
2202 # Strip versions from pkglist and update estimated numbers in flavor.desc
2203 flavor="${2%.flavor}"
2204 set -e
2205 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2206 set +e
2208 flv_dir="$(extract_flavor "$flavor")"
2210 strip_versions "$flv_dir/$flavor.pkglist"
2212 action 'Updating %s...' "$flavor.desc"
2214 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2215 set -- $(module calc_sizes "$flv_dir" "$flavor")
2216 restore_mirrors >/dev/null
2218 sed -i -e '/Image is ready/d' \
2219 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2220 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2221 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2222 -e "s|\(Packages *:\).*$|\1 $4|" \
2223 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2224 "$flv_dir/$flavor.desc"
2226 pack_flavor "$flv_dir" "$flavor"
2227 status
2228 display_unknown "$flv_dir/err"
2229 display_warn "$flv_dir/warn"
2230 cleanup
2231 ;;
2234 extract-flavor)
2235 # Extract a flavor into $FLAVORS_REPOSITORY
2236 flavor="${2%.flavor}"
2237 set -e
2238 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2239 set +e
2241 action 'Extracting %s...' "$flavor.flavor"
2242 flv_dir="$(extract_flavor "$flavor" full)"
2243 storage="$FLAVORS_REPOSITORY/$flavor"
2245 rm -rf "$storage" 2>/dev/null
2246 mkdir -p "$storage"
2247 cp -a "$flv_dir"/* "$storage"
2248 rm "$storage/description"
2249 status
2251 strip_versions "$storage/packages.list"
2253 cleanup
2254 ;;
2257 pack-flavor)
2258 # Create a flavor from $FLAVORS_REPOSITORY.
2259 flavor=${2%.flavor}
2260 storage="$FLAVORS_REPOSITORY/$flavor"
2262 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2264 action 'Creating flavor %s...' "$flavor"
2265 tmp_dir="$(mktemp -d)"
2267 while read from to; do
2268 [ -s "$storage/$from" ] || continue
2269 cp -a "$storage/$from" "$tmp_dir/$to"
2270 done <<EOT
2271 mirrors $flavor.mirrors
2272 distro.sh $flavor-distro.sh
2273 receipt $flavor.receipt
2274 non-free.list $flavor.nonfree
2275 EOT
2277 # Build the package list.
2278 # It can include a list from another flavor with the keyword @include
2279 if [ -s "$storage/packages.list" ]; then
2280 include=$(grep '^@include' "$storage/packages.list")
2281 if [ -n "$include" ]; then
2282 include=${include#@include }
2283 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2284 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2285 else
2286 echo -e "\nERROR: Can't find include package list from $include\n"
2287 fi
2288 fi
2289 # Generate the final/initial package list
2290 [ -s "$storage/packages.list" ] && \
2291 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2292 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2293 fi
2295 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2296 # Process multi-rootfs flavor
2297 . "$storage/receipt"
2298 set -- $ROOTFS_SELECTION
2299 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2300 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2301 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2303 for i in rootcd rootfs; do
2304 mkdir "$tmp_dir/$i"
2305 # Copy extra files from the first flavor
2306 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2307 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2308 # Overload extra files by meta flavor
2309 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2310 [ -n "$(ls $tmp_dir/$i)" ] &&
2311 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2312 dogzip "$tmp_dir/$flavor.$i"
2313 rm -rf "$tmp_dir/$i"
2314 done
2315 else
2316 # Process plain flavor
2317 for i in rootcd rootfs; do
2318 [ -d "$storage/$i" ] || continue
2319 (cd "$storage/$i";
2320 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2321 done
2322 fi
2324 unset VERSION MAINTAINER ROOTFS_SELECTION
2325 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2326 ROOTFS_SIZE="$1 (estimated)"
2327 INITRAMFS_SIZE="$2 (estimated)"
2328 ISO_SIZE="$3 (estimated)"
2329 PKGNUM="$4"
2330 . "$storage/receipt"
2332 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2333 Flavor : $FLAVOR
2334 Description : $SHORT_DESC
2335 Version : $VERSION
2336 Maintainer : $MAINTAINER
2337 LiveCD RAM size : $FRUGAL_RAM
2338 Rootfs list : $ROOTFS_SELECTION
2339 Build date : $(date '+%Y%m%d at %T')
2340 Packages : $PKGNUM
2341 Rootfs size : $ROOTFS_SIZE
2342 Initramfs size : $INITRAMFS_SIZE
2343 ISO image size : $ISO_SIZE
2344 ================================================================================
2346 EOT
2348 rm -f $tmp_dir/packages.list
2349 pack_flavor "$tmp_dir" "$flavor"
2350 status
2351 display_unknown "$tmp_dir/err"
2352 display_warn "$flv_dir/warn"
2353 cleanup
2354 ;;
2357 get-flavor)
2358 # Get a flavor's files and prepare for gen-distro.
2359 flavor=${2%.flavor}
2360 title 'Preparing %s distro flavor' "$flavor"
2361 set -e
2362 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2363 set +e
2365 action 'Cleaning %s...' "$DISTRO"
2366 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2367 # Clean old files
2368 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2369 [ -f "$i" ] && rm "$i"
2370 done
2371 mkdir -p "$DISTRO"
2372 status
2374 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2376 action 'Extracting flavor %s...' "$flavor.flavor"
2377 flv_dir="$(extract_flavor "$flavor" info)"
2378 cp -a "$flv_dir"/* .
2379 mv packages.list distro-packages.list
2380 mv -f info /etc/tazlito
2381 status
2383 for i in rootcd rootfs; do
2384 if [ -d "$i" ]; then
2385 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2386 fi
2387 done
2389 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2390 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2392 action 'Updating %s...' 'tazlito.conf'
2393 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2394 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2395 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2396 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2397 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2398 status
2400 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2401 cleanup
2402 ;;
2405 iso2flavor)
2406 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2407 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2409 FLAVOR=${3%.flavor}
2410 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2411 mount -o loop,ro $2 $TMP_DIR/iso
2412 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2413 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2414 ! -s $TMP_DIR/flavor/*.desc ]; then
2415 _ 'META flavors are not supported.'
2416 umount -d $TMP_DIR/iso
2417 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2418 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2419 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2420 umount -d $TMP_DIR/iso
2421 else
2422 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2423 uncompress $i | \
2424 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2425 done
2426 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2427 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2428 '/etc/slitaz-release' '/boot/rootfs.gz'
2429 umount -d $TMP_DIR/iso
2430 else
2431 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2432 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2433 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2434 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2435 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2436 umount -d $TMP_DIR/iso
2437 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2438 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2439 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2440 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2441 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2442 < $TMP_DIR/rootfs$INSTALLED.md5
2443 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2444 if [ -s $TMP_DIR/flavor/*desc ]; then
2445 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2446 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2447 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2448 for i in rootfs rootcd ; do
2449 [ -s $TMP_DIR/flavor/*.list$i ] &&
2450 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2451 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2452 done
2453 else
2454 find_flavor_rootfs $TMP_DIR/rootfs
2455 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2456 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2457 for i in rootfs rootcd ; do
2458 [ "$(ls $TMP_DIR/$i)" ] &&
2459 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2460 done
2461 unset VERSION MAINTAINER
2462 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2463 if [ -n "$DESCRIPTION" ]; then
2464 _n 'Flavor version : '; read -t 30 VERSION
2465 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2466 fi
2468 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2469 Flavor : $FLAVOR
2470 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2471 Version : ${VERSION:-1.0}
2472 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2473 LiveCD RAM size : $RAM_SIZE
2474 Build date : $BUILD_DATE
2475 Packages : $PKGCNT
2476 Rootfs size : $ROOTFS_SIZE
2477 Initramfs size : $INITRAMFS_SIZE
2478 ISO image size : $ISO_SIZE
2479 ================================================================================
2481 EOT
2482 longline "Tazlito can't detect each file installed during \
2483 a package post_install. You should extract this flavor (tazlito extract-flavor \
2484 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2485 tree and remove files generated by post_installs.
2486 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2487 repack the flavor (tazlito pack-flavor $FLAVOR)"
2488 fi
2489 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2490 fi
2491 fi
2492 rm -rf $TMP_DIR
2493 ;;
2496 gen-distro)
2497 # Generate a live distro tree with a set of packages.
2499 check_root
2500 start_time=$(date +%s)
2502 # Tazlito options: --iso or --cdrom
2503 CDROM=''
2504 [ -n "$iso" ] && CDROM="-o loop $iso"
2505 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2507 # Check if a package list was specified on cmdline.
2508 if [ -f "$2" ]; then
2509 LIST_NAME="$2"
2510 else
2511 LIST_NAME='distro-packages.list'
2512 fi
2514 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2515 'Please clean the distro tree or change directory path.'
2516 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2517 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2519 # If list not given: build list with all installed packages
2520 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2521 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2522 fi
2524 # Exit if no list name.
2525 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2527 # Start generation.
2528 title 'Tazlito generating a distro'
2530 # Misc checks
2531 mkdir -p "$PACKAGES_REPOSITORY"
2532 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2533 newline
2535 # Mount CD-ROM to be able to repack boot-loader packages
2536 if [ ! -e /boot -a -n "$CDROM" ]; then
2537 mkdir $TMP_MNT
2538 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2539 ln -s "$TMP_MNT/boot" /
2540 if [ ! -d "$ADDFILES/rootcd" ] ; then
2541 mkdir -p "$ADDFILES/rootcd"
2542 for i in $(ls $TMP_MNT); do
2543 [ "$i" == 'boot' ] && continue
2544 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2545 done
2546 fi
2547 else
2548 rmdir "$TMP_MNT"
2549 fi
2550 fi
2552 # Rootfs stuff.
2553 echo 'Preparing the rootfs directory...'
2554 mkdir -p "$ROOTFS"
2555 export root="$ROOTFS"
2556 # pass current 'mirror' to the root
2557 mkdir -p $root/var/lib/tazpkg $root/etc
2558 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2559 cp -f /etc/slitaz-release $root/etc/slitaz-release
2560 strip_versions "$LIST_NAME"
2562 if [ "$REPACK" == 'y' ]; then
2563 # Determine full packages list with all dependencies
2564 tmp_dir="$(mktemp -d)"
2565 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2566 touch "$tmp_dir/full.pkglist"
2567 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2569 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2570 while read pkgname pkgver; do
2571 # Is package in full list?
2572 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2573 # Is package already repacked?
2574 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2575 _ 'Repacking %s...' "$pkgname-$pkgver"
2576 tazpkg repack "$pkgname" --quiet
2577 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2578 status
2579 done
2581 rm -r "$tmp_dir"
2582 fi
2584 if [ -f non-free.list ]; then
2585 # FIXME: working in the ROOTFS chroot?
2586 newline
2587 echo 'Preparing non-free packages...'
2588 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2589 for pkg in $(cat 'non-free.list'); do
2590 if [ ! -d "$INSTALLED/$pkg" ]; then
2591 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2592 tazpkg get-install get-$pkg
2593 fi
2594 get-$pkg "$ROOTFS"
2595 fi
2596 tazpkg repack $pkg
2597 pkg=$(ls $pkg*.tazpkg)
2598 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2599 mv $pkg $PACKAGES_REPOSITORY
2600 done
2601 fi
2602 cp $LIST_NAME $DISTRO/distro-packages.list
2603 newline
2605 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2607 cd $DISTRO
2608 cp distro-packages.list $ROOTFS/etc/tazlito
2609 # Copy all files from $ADDFILES/rootfs to the rootfs.
2610 if [ -d "$ADDFILES/rootfs" ] ; then
2611 action 'Copying addfiles content to the rootfs...'
2612 cp -a $ADDFILES/rootfs/* $ROOTFS
2613 status
2614 fi
2616 action 'Root filesystem is generated...'; status
2618 # Root CD part.
2619 action 'Preparing the rootcd directory...'
2620 mkdir -p $ROOTCD
2621 status
2623 # Move the boot dir with the Linux kernel from rootfs.
2624 # The efi & boot dirs go directly on the CD.
2625 if [ -d "$ROOTFS/efi" ] ; then
2626 action 'Moving the efi directory...'
2627 mv $ROOTFS/efi $ROOTCD
2628 status
2629 fi
2630 if [ -d "$ROOTFS/boot" ] ; then
2631 action 'Moving the boot directory...'
2632 mv $ROOTFS/boot $ROOTCD
2633 cd $ROOTCD/boot
2634 rm -rf grub*
2635 make_bzImage_hardlink
2636 status
2637 fi
2638 cd $DISTRO
2639 # Copy all files from $ADDFILES/rootcd to the rootcd.
2640 if [ -d "$ADDFILES/rootcd" ] ; then
2641 action 'Copying addfiles content to the rootcd...'
2642 cp -a $ADDFILES/rootcd/* $ROOTCD
2643 status
2644 fi
2645 # Execute the distro script used to perform tasks in the rootfs
2646 # before compression. Give rootfs path in arg
2647 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2648 if [ -x "$DISTRO_SCRIPT" ]; then
2649 echo 'Executing distro script...'
2650 sh $DISTRO_SCRIPT $DISTRO
2651 fi
2653 # Execute the custom_rules() found in receipt.
2654 if [ -s "$TOP_DIR/receipt" ]; then
2655 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2656 echo -e "Executing: custom_rules()\n"
2657 . "$TOP_DIR/receipt"
2658 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2659 fi
2660 fi
2662 # Multi-rootfs
2663 if [ -s /etc/tazlito/rootfs.list ]; then
2665 FLAVOR_LIST="$(awk '{
2666 for (i = 2; i <= NF; i+=2)
2667 printf "%s ", $i;
2668 }' /etc/tazlito/rootfs.list)"
2670 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2671 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2672 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2674 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2675 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2676 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2677 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2679 n=0
2680 last=$ROOTFS
2681 while read flavor; do
2682 n=$(($n+1))
2683 mkdir ${ROOTFS}0$n
2684 export root="${ROOTFS}0$n"
2685 # initial tazpkg setup in empty rootfs
2686 tazpkg --root=$root >/dev/null 2>&1
2688 newline
2689 boldify "Building $flavor rootfs..."
2691 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2692 cp "$TOP_DIR/$flavor.flavor" .
2694 if [ ! -s "$flavor.flavor" ]; then
2695 # We may have it in $FLAVORS_REPOSITORY
2696 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2697 tazlito pack-flavor $flavor
2698 else
2699 download $flavor.flavor
2700 fi
2701 fi
2703 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2704 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2705 cp $flavor.pkglist $DISTRO/list-packages0$n
2706 status
2708 strip_versions "$DISTRO/list-packages0$n"
2710 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2712 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 else
2744 # Initramfs and ISO image stuff.
2745 gen_initramfs $ROOTFS
2746 fi
2747 gen_livecd_isolinux
2748 distro_stats
2749 cleanup
2750 ;;
2753 clean-distro)
2754 # Remove old distro tree.
2756 check_root
2757 title 'Cleaning: %s' "$DISTRO"
2758 if [ -d "$DISTRO" ] ; then
2759 if [ -d "$ROOTFS" ] ; then
2760 action 'Removing the rootfs...'
2761 rm -f $DISTRO/$INITRAMFS
2762 rm -rf $ROOTFS
2763 status
2764 fi
2765 if [ -d "$ROOTCD" ] ; then
2766 action 'Removing the rootcd...'
2767 rm -rf $ROOTCD
2768 status
2769 fi
2770 action 'Removing eventual ISO image...'
2771 rm -f $DISTRO/$ISO_NAME.iso
2772 rm -f $DISTRO/$ISO_NAME.md5
2773 status
2774 fi
2775 footer
2776 ;;
2779 check-distro)
2780 # Check for a few LiveCD needed files not installed by packages.
2782 # TODO: Remove this function.
2783 # First two files are maintained by tazpkg while it runs on rootfs,
2784 # while last one file should be maintained by tazlito itself.
2785 check_rootfs
2786 title 'Checking distro: %s' "$ROOTFS"
2787 # SliTaz release info.
2788 rel='/etc/slitaz-release'
2789 if [ ! -f "$ROOTFS$rel" ]; then
2790 _ 'Missing release info: %s' "$rel"
2791 else
2792 action 'Release : %s' "$(cat $ROOTFS$rel)"
2793 status
2794 fi
2795 # Tazpkg mirror.
2796 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2797 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2798 todomsg
2799 else
2800 action 'Mirror configuration exists...'
2801 status
2802 fi
2803 # Isolinux msg
2804 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2805 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2806 todomsg
2807 else
2808 action 'Isolinux message seems good...'
2809 status
2810 fi
2811 footer
2812 ;;
2815 writeiso)
2816 # Writefs to ISO image including /home unlike gen-distro we don't use
2817 # packages to generate a rootfs, we build a compressed rootfs with all
2818 # the current filesystem similar to 'tazusb writefs'.
2820 DISTRO='/home/slitaz/distro'
2821 ROOTCD="$DISTRO/rootcd"
2822 COMPRESSION="${2:-none}"
2823 ISO_NAME="${3:-slitaz}"
2824 check_root
2825 # Start info
2826 title 'Write filesystem to ISO'
2827 longline "The command writeiso will write the current filesystem into a \
2828 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2829 newline
2830 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2832 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2833 # Save some space
2834 rm -rf /var/cache/tazpkg/*
2835 rm -f /var/lib/tazpkg/*.bak
2836 rm -rf $DISTRO
2838 # Optionally remove sound card selection and screen resolution.
2839 if [ -z $LaunchedByTazpanel ]; then
2840 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2841 case $anser in
2842 y)
2843 action 'Removing current sound card and screen configurations...'
2844 rm -f /var/lib/sound-card-driver
2845 rm -f /var/lib/alsa/asound.state
2846 rm -f /etc/X11/xorg.conf ;;
2847 *)
2848 action 'Keeping current sound card and screen configurations...' ;;
2849 esac
2850 status
2851 newline
2853 # Optionally remove i18n settings
2854 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2855 case $anser in
2856 y)
2857 action 'Removing current locale/keymap settings...'
2858 newline > /etc/locale.conf
2859 newline > /etc/keymap.conf ;;
2860 *)
2861 action 'Keeping current locale/keymap settings...' ;;
2862 esac
2863 status
2864 fi
2866 # Clean-up files by default
2867 newline > /etc/udev/rules.d/70-persistent-net.rules
2868 newline > /etc/udev/rules.d/70-persistant-cd.rules
2870 # Create list of files including default user files since it is defined in /etc/passwd
2871 # and some new users might have been added.
2872 cd /
2873 echo 'init' > /tmp/list
2874 for dir in bin etc sbin var dev lib root usr home opt; do
2875 [ -d $dir ] && find $dir
2876 done >> /tmp/list
2878 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2879 [ -d $dir ] && echo $dir
2880 done >> /tmp/list
2882 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2884 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2885 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2886 #fi
2887 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2888 touch /var/log/wtmp
2890 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2891 sed -i "/var\/log\/$removelog/d" /tmp/list
2892 done
2894 # Generate initramfs with specified compression and display rootfs
2895 # size in realtime.
2896 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2898 write_initramfs &
2899 sleep 2
2900 cd - > /dev/null
2901 echo -en "\nFilesystem size:"
2902 while [ ! -f /tmp/rootfs ]; do
2903 sleep 1
2904 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2905 done
2906 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2907 echo -e "\n"
2908 rm -f /tmp/rootfs
2910 # Move freshly generated rootfs to the cdrom.
2911 mkdir -p $ROOTCD/boot
2912 mv -f /$INITRAMFS $ROOTCD/boot
2913 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2915 # Now we need the kernel and isolinux files.
2916 copy_from_cd() {
2917 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2918 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2919 unmeta_boot $ROOTCD
2920 umount /media/cdrom
2923 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2924 copy_from_cd;
2925 elif mount | grep /media/cdrom; then
2926 copy_from_cd;
2927 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2928 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2929 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2930 else
2931 touch /tmp/.write-iso-error
2932 longline "When SliTaz is running in RAM the kernel and bootloader \
2933 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2934 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2935 echo -en "----\nENTER to continue..."; read i
2936 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2937 copy_from_cd
2938 fi
2940 # Generate the iso image.
2941 touch /tmp/.write-iso
2942 newline
2943 cd $DISTRO
2944 create_iso $ISO_NAME.iso $ROOTCD
2945 action 'Creating the ISO md5sum...'
2946 md5sum $ISO_NAME.iso > $ISO_NAME.md5
2947 status
2949 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
2950 rm -f /tmp/.write-iso
2952 if [ -z $LaunchedByTazpanel ]; then
2953 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
2954 case $anser in
2955 y)
2956 umount /dev/cdrom 2>/dev/null
2957 eject
2958 echo -n "Please insert a blank CD-ROM and press ENTER..."
2959 read i && sleep 2
2960 tazlito burn-iso $DISTRO/$ISO_NAME.iso
2961 echo -en "----\nENTER to continue..."; read i ;;
2962 *)
2963 exit 0 ;;
2964 esac
2965 fi
2966 ;;
2969 burn-iso)
2970 # Guess CD-ROM device, ask user and burn the ISO.
2972 check_root
2973 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
2974 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
2975 # We can specify an alternative ISO from the cmdline.
2976 iso="${2:-$DISTRO/$ISO_NAME.iso}"
2977 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
2979 title 'Tazlito burn ISO'
2980 echo "CD-ROM device : /dev/$DRIVE_NAME"
2981 echo "Drive speed : $DRIVE_SPEED"
2982 echo "ISO image : $iso"
2983 footer
2985 case $(yesorno 'Burn ISO image?' 'n') in
2986 y)
2987 title 'Starting Wodim to burn the ISO...'
2988 sleep 2
2989 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
2990 footer 'ISO image is burned to CD-ROM.'
2991 ;;
2992 *)
2993 die 'Exiting. No ISO burned.'
2994 ;;
2995 esac
2996 ;;
2999 merge)
3000 # Merge multiple rootfs into one iso.
3002 if [ -z "$2" ]; then
3003 cat <<EOT
3004 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3006 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3007 i.e: rootfsN is a subset of rootfsN-1
3008 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3009 The boot loader will select the rootfs according to the RAM size detected.
3011 Example:
3012 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3014 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3015 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3017 EOT
3018 exit 2
3019 fi
3021 shift # skip merge
3022 append="$1 slitaz1"
3023 shift # skip size1
3024 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3026 ISO=$1.merged
3028 # Extract filesystems
3029 action 'Mounting %s' "$1"
3030 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3031 status || cleanup_merge
3033 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3034 make_bzImage_hardlink $TMP_DIR/iso/boot
3035 umount -d $TMP_DIR/mnt
3036 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3037 _ '%s is already a merged iso. Aborting.' "$1"
3038 cleanup_merge
3039 fi
3040 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3041 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3042 if [ ! -f /boot/isolinux/ifmem.c32 -a
3043 ! -f /boot/isolinux/c32box.c32 ]; then
3044 cat <<EOT
3045 No file /boot/isolinux/ifmem.c32
3046 Please install syslinux package !
3047 EOT
3048 rm -rf $TMP_DIR
3049 exit 1
3050 fi
3051 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3052 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3053 fi
3055 action 'Extracting %s' 'iso/rootfs.gz'
3056 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3057 [ -d $TMP_DIR/rootfs1/etc ]
3058 status || cleanup_merge
3060 n=1
3061 while [ -n "$2" ]; do
3062 shift # skip rootfs N-1
3063 p=$n
3064 n=$(($n + 1))
3065 append="$append $1 slitaz$n"
3066 shift # skip size N
3067 mkdir -p $TMP_DIR/rootfs$n
3069 action 'Extracting %s' "$1"
3070 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3071 [ -d "$TMP_DIR/rootfs$n/etc" ]
3072 status || cleanup_merge
3074 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3075 action 'Creating %s' "rootfs$p.gz"
3076 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3077 status
3078 done
3079 action 'Creating %s' "rootfs$n.gz"
3080 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3081 status
3082 rm -f $TMP_DIR/iso/boot/rootfs.gz
3083 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3084 create_iso $ISO $TMP_DIR/iso
3085 rm -rf $TMP_DIR
3086 ;;
3089 repack)
3090 # Repack an iso with maximum lzma compression ratio.
3092 ISO=$2
3093 mkdir -p $TMP_DIR/mnt
3095 # Extract filesystems
3096 action 'Mounting %s' "$ISO"
3097 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3098 status || cleanup_merge
3100 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3101 umount -d $TMP_DIR/mnt
3103 for i in $TMP_DIR/iso/boot/rootfs* ; do
3104 action 'Repacking %s' "$(basename $i)"
3105 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3106 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3107 align_to_32bits $i
3108 status
3109 done
3111 create_iso $ISO $TMP_DIR/iso
3112 rm -rf $TMP_DIR
3113 ;;
3116 build-loram)
3117 # Build a Live CD for low RAM systems.
3119 ISO="$2"
3120 OUTPUT="$3"
3121 [ -z "$3" ] && \
3122 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3123 mkdir -p "$TMP_DIR/iso"
3124 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3125 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3126 if ! check_iso_for_loram ; then
3127 umount -d "$TMP_DIR/iso"
3128 die "$ISO is not a valid SliTaz live CD. Abort."
3129 fi
3130 case "$4" in
3131 cdrom) build_loram_cdrom ;;
3132 http) build_loram_http ;;
3133 *) build_loram_ram "$5" ;;
3134 esac
3135 umount $TMP_DIR/iso # no -d: needs /proc
3136 losetup -d $loopdev
3137 rm -rf $TMP_DIR
3138 ;;
3141 emu-iso)
3142 # Emulate an ISO image with Qemu.
3143 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3144 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3145 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3146 echo -e "\nStarting Qemu emulator:\n"
3147 echo -e "qemu $QEMU_OPTS $iso\n"
3148 qemu $QEMU_OPTS $iso
3149 ;;
3152 deduplicate)
3153 # Deduplicate files in a tree
3154 shift
3155 deduplicate "$@"
3156 ;;
3159 usage|*)
3160 # Print usage also for all unknown commands.
3161 usage
3162 ;;
3163 esac
3165 exit 0