tazlito view tazlito @ rev 487

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