tazlito view tazlito @ rev 498

uefi: fix fat12
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed May 16 10:03:24 2018 +0200 (2018-05-16)
parents 2f9336b7c290
children 6b369e63e8f6
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-2018 SliTaz - GNU General Public License.
11 #
12 # Authors: see the AUTHORS file
13 #
15 VERSION='6.0'
17 . /lib/libtaz.sh
18 # Force to use Busybox cpio and wget
19 alias cpio='busybox cpio'
20 alias wget='busybox wget'
21 alias stat='busybox stat'
22 alias awk='busybox awk'
24 # Tazlito configuration variables to be shorter
25 # and to use words rather than numbers.
26 COMMAND="$1"
27 LIST_NAME="$2"
28 TMP_DIR="/tmp/tazlito-$$-$RANDOM"
29 TMP_MNT="/media/tazlito-$$-$RANDOM"
30 TOP_DIR="$(pwd)"
31 INITRAMFS='rootfs.gz'
32 LOCALSTATE='/var/lib/tazpkg'
33 INSTALLED="$LOCALSTATE/installed"
34 CACHE_DIR='/var/cache/tazpkg'
35 MIRROR="$LOCALSTATE/mirror"
36 DEFAULT_MIRROR="http://mirror1.slitaz.org/packages/$(cat /etc/slitaz-release)/"
38 log='/var/log/tazlito.log'
39 if [ $(id -u) -eq 0 ]; then
40 newline > $log
41 fi
44 cleanup() {
45 if [ -d "$TMP_MNT" ]; then
46 umount $TMP_MNT
47 rmdir $TMP_MNT
48 rm -f /boot
49 fi
50 [ -d "$tmp_dir" ] && rm -r "$tmp_dir"
51 [ -d "$flv_dir" ] && rm -r "$flv_dir"
52 }
55 # Report error and finish work
57 die() {
58 emsg "<n>$(longline "$@")<n> " >&2
59 cleanup
60 exit 1
61 }
64 # Run Tazlito module
65 module() {
66 local mod="$1"; shift
67 /usr/libexec/tazlito/$mod $@
68 }
72 # Try to include config file, continue if command is gen-config or exit.
73 # The main config used by default is in /etc/tazlito.
74 # Specific distro config file can be put in a distro tree.
75 for i in /etc/tazlito "$TOP_DIR"; do
76 [ -f "$i/tazlito.conf" ] && CONFIG_FILE="$i/tazlito.conf"
77 done
79 [ -z "$CONFIG_FILE" -a "$COMMAND" != 'gen-config' ] && \
80 die 'Unable to find any configuration file.' \
81 'Please read the docs or run `tazlito gen-config` to get an empty config file.'
83 . $CONFIG_FILE
85 # While Tazpkg is not used the default mirror URL file does not exist
86 # and user can't recharge the list of flavors.
87 [ $(id -u) -eq 0 -a ! -f "$MIRROR" ] && echo "$DEFAULT_MIRROR" > $MIRROR
89 # Set the rootfs and rootcd path with $DISTRO
90 # configuration variable.
91 ROOTFS="$DISTRO/rootfs"
92 ROOTCD="$DISTRO/rootcd"
97 #####################
98 # Tazlito functions #
99 #####################
102 # Print the usage.
104 usage () {
105 [ $(basename $0) == 'tazlito' ] && cat <<EOT
107 SliTaz Live Tool - Version: $(colorize 34 "$VERSION")
109 $(boldify "Usage:") tazlito [command] [list|iso|flavor|compression] [dir|iso]
111 $(boldify "Commands:")
112 EOT
113 optlist "\
114 usage Print this short usage.
115 stats View Tazlito and distro configuration statistics.
116 list-addfiles Simple list of additional files in the rootfs.
117 gen-config Generate a new configuration file for a distro.
118 configure Configure the main config file or a specific tazlito.conf.
119 gen-iso Generate a new ISO from a distro tree.
120 gen-initiso Generate a new initramfs and ISO from the distro tree.
121 list-flavors List all flavors available on the mirror.
122 gen-flavor Generate a new Live CD description.
123 gen-liveflavor Generate a Live CD description from current system.
124 show-flavor Show Live CD description.
125 get-flavor Get a flavor's list of packages (--noup to skip update).
126 upgrade-flavor Update package list to the latest available versions.
127 extract-flavor Extract a *.flavor file into $FLAVORS_REPOSITORY.
128 pack-flavor Pack (and update) a flavor from $FLAVORS_REPOSITORY.
129 iso2flavor Create a flavor file from a SliTaz ISO image.
130 extract-distro Extract an ISO to a directory and rebuild Live CD tree.
131 gen-distro Generate a Live distro and ISO from a list of packages.
132 clean-distro Remove all files generated by gen-distro.
133 check-distro Help to check if distro is ready to release.
134 writeiso Use running system to generate a bootable ISO (with /home).
135 merge Merge multiple rootfs into one ISO.
136 deduplicate Deduplicate files in a tree.
137 repack Recompress rootfs into ISO with maximum ratio.
138 build-loram Generate a Live CD for low-RAM systems.
139 emu-iso Emulate an ISO image with QEMU.
140 burn-iso Burn ISO image to a CD-ROM using Wodim.
141 "
142 }
145 yesorno() {
146 local answer
147 echo -n "$1 (y=yes, n=no) [$2] " >&2
148 case "$DEFAULT_ANSWER" in
149 Y|y) answer="y";;
150 N|n) answer="n";;
151 *)
152 read -t 30 answer
153 [ -z "$answer" ] && answer="$2"
154 [ "$answer" != 'y' -a "$answer" != 'n' ] && answer="$2"
155 ;;
156 esac
157 echo "$answer"
158 }
161 field() {
162 grep "^$1" "$2" | \
163 case "$1" in
164 Desc*) sed 's|^.*: *||';;
165 *) sed 's/.*: \([0-9KMG\.]*\).*/\1/';;
166 esac
167 }
170 todomsg() {
171 echo -e "\\033[70G[ \\033[1;31mTODO\\033[0;39m ]"
172 }
175 # Download a file from this mirror
177 download_from() {
178 local i mirrors="$1"
179 shift
180 for i in $mirrors; do
181 case "$i" in
182 http://*|ftp://*|https://*)
183 wget -c $i$@ && break;;
184 *)
185 cp $i/$1 . && break;;
186 esac
187 done
188 }
191 # Download a file trying all mirrors
193 download() {
194 local i
195 for i in $(cat $MIRROR $LOCALSTATE/undigest/*/mirror 2>/dev/null); do
196 download_from "$i" "$@" && break
197 done
198 }
201 # Execute hooks provided by some packages
203 genisohooks() {
204 local here="$(pwd)"
205 for i in $(ls $ROOTFS/etc/tazlito/*.$1 2>/dev/null); do
206 cd $ROOTFS
207 . $i $ROOTCD
208 done
209 cd "$here"
210 }
213 # Echo the package name if the tazpkg is already installed
215 installed_package_name() {
216 local tazpkg="$1" package VERSION EXTRAVERSION
218 # Try to find package name and version to be able
219 # to repack it from installation
220 # A dash (-) can exist in name *and* in version
221 package=${tazpkg%-*}
222 i=$package
223 while true; do
224 unset VERSION EXTRAVERSION
225 eval $(grep -s ^VERSION= $INSTALLED/$i/receipt)
226 eval $(grep -s ^EXTRAVERSION= $INSTALLED/$i/receipt)
227 if [ "$i-$VERSION$EXTRAVERSION" == "$tazpkg" ]; then
228 echo $i
229 break
230 fi
231 case "$i" in
232 *-*);;
233 *) break;;
234 esac
235 i=${i%-*}
236 done
237 }
240 # Check for the rootfs tree.
242 check_rootfs() {
243 [ -d "$ROOTFS/etc" ] || die 'Unable to find a distro rootfs...'
244 }
247 # Check for the boot dir into the root CD tree.
249 verify_rootcd() {
250 [ -d "$ROOTCD/boot" ] || die 'Unable to find the rootcd boot directory...'
251 }
253 set32() {
254 for i in $(seq 0 8 $((${4:-32}-8))); do
255 printf '\\\\x%02X' $((($2 >> $i) & 255))
256 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
257 }
259 set64() {
260 for i in $(seq 0 8 24 ; seq 24 -8 0); do
261 printf '\\\\x%02X' $((($2 >> $i) & 255))
262 done | xargs echo -en | dd bs=1 conv=notrunc of=$3 seek=$1 2>/dev/null
263 }
266 first_block() {
267 busybox stat -m "$1" | sed q
268 }
272 # Force size and location in the 2nd eltorito boot file (/boot/isolinux/efi.img)
274 fix_efi_boot_img_size() {
275 local n=$3
276 [ $n -gt 65535 ] && n=65535
277 set32 $((0x66+2048*$(first_block $2/boot/isolinux/boot.cat))) $n $1 16
278 set32 $((0x1C+2048*$4)) $(($4*4)) $1
279 }
282 # Force the size for the /boot/isolinux/efi.img file
284 fix_efi_img_size() {
285 local e=$((0x809C))
286 for i in BOOT ISOLINUX EFI.IMG ; do
287 local sz=$(get $(($e+10)) "$2" 4)
288 e=$(($(get $(($e+2)) "$2" 4) * 2048))
289 while [ $sz -gt 0 ]; do
290 local len=$(get $e "$2")
291 [ "$(dd if="$2" bs=1 skip=$(($e+33)) count=${#i} \
292 2>/dev/null)" == "$i" ] && continue 2
293 [ $len -eq 0 ] && break
294 sz=$(($sz-$len))
295 e=$(($e+$len))
296 done
297 return # not found
298 done
299 set64 $(($e+10)) $1 "$2"
300 }
303 # create /boot/isolinux/efi.img to share EFI files with the iso image
305 fixup_uefi_part() {
306 [ -s $2/boot/isolinux/efi.img ] || return
307 local n=$(get 19 "$2/boot/isolinux/efi.img")
308 [ $n -eq 0 ] && n=$(get 32 "$2/boot/isolinux/efi.img" 4)
309 efiblock=$(first_block "$2/boot/isolinux/efi.img")
310 fix_efi_img_size $(($n*512)) $1
311 fix_efi_boot_img_size $1 $2 $n $efiblock
313 # Build file list tree
314 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
315 resv=$(get 14 "$2/boot/isolinux/efi.img")
316 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
317 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead=4 }
318 {
319 if (skiphead!=0) {
320 if ($1=="*") skiphead--
321 next
322 }
323 if (skipdot!=0) {
324 if (skipdot==2) up[cur]=$13 $12
325 else cur=$13 $12
326 skipdot=0
327 next
328 }
329 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
330 if ($3=="2e") skipdot=2
331 else skipdot=1
332 next
333 }
334 if (gotname!=0) {
335 path=""
336 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
337 if (gotname==2) dir[$13 $12]=name
338 else print $1 " " $13 $12 " " path name
339 gotname=0
340 name=""
341 next
342 }
343 if (s!="") {
344 if (eos==0)
345 for (i=2;i<18;i+=2) {
346 if (i==12) i+=2
347 if ($i=="00") break
348 s=s substr($0,i+60,1)
349 }
350 name=s name
351 s=""
352 eos=0
353 next
354 }
355 if ($13=="0f") {
356 s=""
357 for (i=3;i<16;i+=2) {
358 if (i==13) i+=3
359 if ($i=="00") { eos=1; break }
360 s=s substr($0,i+60,1)
361 }
362 next
363 }
364 if ($13=="10") {
365 name=name "/"
366 gotname=2
367 next
368 }
369 if ($13=="20") {
370 gotname=1
371 next
372 }
373 }
374 ' | ( while read offset cluster file; do
375 cluster=$(($(first_block "$2/$file")-$basecluster))
376 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
377 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
378 done
380 # Update fat12 or fat16
381 get 57 "$2/boot/isolinux/efi.img"
382 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
383 od -An -t u1 -w1 -v
384 ) | awk '
385 {
386 if (state==0) {
387 if ($2=="") {
388 if ($1==12849) fat=12
389 else fat=16
390 state++
391 }
392 else {
393 for (i=1;i<$2;i++) c[$1+i]=$1+i
394 c[$1+$2]=65535
395 }
396 next
397 }
398 if (state==1) {
399 prev=$1
400 state++
401 next
402 }
403 if (state==2) {
404 if (fat==12) {
405 n=($1%16)*256+prev
406 if (n!=0) c[pos+1]=n
407 pos++
408 prev=int($1/16)
409 state++
410 next
411 }
412 n=$1*256+prev
413 }
414 else if (state==3) {
415 n=$1*16+prev
416 }
417 if (n!=0) c[pos+1]=n
418 pos++
419 state=1
420 }
421 END {
422 for (i=1;i<=pos;i+=2) {
423 if (c[i]=="") c[i]=0
424 if (c[i+1]=="") c[i+1]=0
425 if (fat==12) printf "0 %02X %1X%1X %02X |\n",c[i]%256,c[i+1]%16,(c[i]/256)%16,(c[i+1]/16)%256
426 else printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,c[i+1]%256,(c[i+1]/256)%256
427 }
428 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
429 conv=notrunc bs=512 > /dev/null 2>&1
430 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
431 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
433 # Cleanup cache
434 umount $2
435 mount -o loop,ro $1 $2
436 }
439 # allocate efi.img stub to share EFI files in the EFI boot partition
441 alloc_uefi_part() {
442 local basedir=$(dirname "$1")/..
443 local fclust=$({
444 [ -d $basedir/efi ] &&
445 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
446 while [ -s "$1" ]; do
447 local efifile
448 case "$1" in
449 *taz) efifile=bootia32.efi ;;
450 *taz64) efifile=bootx64.efi ;;
451 esac
452 if [ ! -s $basedir/efi/boot/$efifile ] &&
453 [ $(get $((0x82)) "$1") == $((0x4550)) ]; then
454 mkdir -p $basedir/efi/boot 2> /dev/null
455 for i in "$1" $basedir/boot/rootfs* ; do
456 ln "$i" $basedir/efi/boot/
457 stat -c "%s %n" "$i"
458 done 2> /dev/null
459 cat >> $basedir/efi/boot/startup.nsh <<EOT
460 FS0:\\EFI\\BOOT\\$(basename $1) rw root=0x100 autologin\
461 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
462 [ "$efifile" == "bootx64.efi" -a -s $basedir/efi/boot/${f}64 ] && \
463 f=${f}64; echo -n " initrd=/EFI/BOOT/$f";done)
464 EOT
465 fi
466 shift
467 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
468 [ ${fclust:-0} -eq 0 ] && return
469 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
470 BEGIN {
471 FS="/"
472 }
473 NF > 1 {
474 d[NF $NF]+=2
475 d[NF-1 $(NF-1)]+=($NF+25)/13
476 }
477 END {
478 for (i in d)
479 n+=int((d[i]+63)/64)
480 print n
481 }')
482 local clusters=$(($fclust+$dclust))
483 if [ $clusters -lt 4085 ]; then
484 fsect=$(((($clusters+2)*3+1023)/1024))
485 ftype="31 32"
486 fhead="F8 FF FF"
487 else
488 fsect=$((($clusters+2+255)/256))
489 ftype="31 36"
490 fhead="F8 FF FF FF"
491 fi
492 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
493 fsz="$(printf "%02X %02X" $(($fsect%256)) $((($fsect>>8)%256)))"
494 # reserved + fat*2 + root dir + dirs
495 count=$((($rsect + $fsect*2)/4 + 2 + $dclust ))
496 s=$((($count+$fclust)*4))
497 if [ $s -gt 65535 ]; then
498 size="00 00"
499 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
500 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
501 else
502 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
503 size32="00 00 00 00"
504 fi
505 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
506 count=$s 2> /dev/null
508 # Create boot sector
509 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
510 seek=510 bs=1 conv=notrunc 2> /dev/null
511 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
512 conv=notrunc 2> /dev/null
513 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
514 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
515 0 $size32 80 00 29 00 00 00 00 4e 4f 20 4e 41 |
516 0 4d 45 20 20 20 20 46 41 54 $ftype 20 20 20 cd 18 |
517 0 cd 19 eb fa |
518 EOT
520 # Create fats
521 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
522 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
523 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
524 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
526 mkdir -p /tmp/mnt$$
527 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
528 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
529 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
530 sync
531 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
532 skip=$rsect bs=512 count=$fsect 2> /dev/null
533 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
534 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
535 umount /tmp/mnt$$
536 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
537 seek=$rsect bs=512 conv=notrunc 2> /dev/null
538 rm /tmp/fat$$
539 rmdir /tmp/mnt$$
541 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
542 seek=$count 2> /dev/null
543 }
546 # isolinux.conf doesn't know the kernel version.
547 # We name the kernel image 'bzImage'.
548 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
550 make_bzImage_hardlink() {
551 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
552 rm -f ${1:-.}/bzImage 2>/dev/null
553 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
554 fi
555 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
556 rm -f ${1:-.}/bzImage64 2> /dev/null
557 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
558 fi
559 }
562 create_iso() {
563 cd $2
564 deduplicate
566 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
567 make_bzImage_hardlink $2/boot
568 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
570 cat > /tmp/cdsort$$ <<EOT
571 $PWD/boot/isolinux 100
572 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
573 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
574 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
575 $PWD/boot/isolinux/efi.img 300
576 $PWD/boot/isolinux/isolinux.bin 399
577 $PWD/boot/isolinux/boot.cat 400
578 EOT
580 action 'Computing md5...'
581 touch boot/isolinux/boot.cat
582 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
583 sort -k 2 > md5sum
584 status
586 cd - >/dev/null
587 title 'Generating ISO image'
589 _ 'Generating %s' "$1"
590 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
591 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
592 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
593 -no-emul-boot -boot-load-size 4 -boot-info-table \
594 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
595 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
596 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
597 -A "tazlito $VERSION/$(genisoimage --version)" \
598 -copyright README -P "www.slitaz.org" -no-pad $2
599 rm -f /tmp/cdsort$$
600 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
602 mkdir /tmp/mnt$$
603 mount -o loop,ro $1 /tmp/mnt$$
604 fixup_uefi_part $1 /tmp/mnt$$
605 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
606 ${uefi:+boot/isolinux/efi.img} ; do
607 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
608 done
609 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
610 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
611 umount -d /tmp/mnt$$
612 rmdir /tmp/mnt$$
614 if [ -s '/etc/tazlito/info' ]; then
615 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
616 action 'Storing ISO info...'
617 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
618 status
619 fi
620 fi
622 if [ -x '/usr/bin/isohybrid' ]; then
623 action 'Creating hybrid ISO...'
624 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
625 status
626 fi
628 if [ -x '/usr/bin/iso2exe' ]; then
629 echo 'Creating EXE header...'
630 /usr/bin/iso2exe $1 2>/dev/null
631 fi
632 }
635 # Generate a new ISO image using isolinux.
637 gen_livecd_isolinux() {
638 # Some packages may want to alter iso
639 genisohooks iso
640 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
642 # Set date for boot msg.
643 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
644 DATE=$(date +%Y%m%d)
645 action 'Setting build date to: %s...' "$DATE"
646 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
647 status
648 fi
650 cd $DISTRO
651 create_iso $ISO_NAME.iso $ROOTCD
653 action 'Creating the ISO md5sum...'
654 md5sum $ISO_NAME.iso > $ISO_NAME.md5
655 status
657 separator
658 # Some packages may want to alter final iso
659 genisohooks final
660 }
663 lzma_history_bits() {
664 #
665 # This generates an ISO which boots with Qemu but gives
666 # rootfs errors in frugal or liveUSB mode.
667 #
668 # local n
669 # local sz
670 # n=20 # 1Mb
671 # sz=$(du -sk $1 | cut -f1)
672 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
673 # n=$(( $n + 1 ))
674 # sz=$(( $sz / 2 ))
675 # done
676 # echo $n
677 echo ${LZMA_HISTORY_BITS:-24}
678 }
681 lzma_switches() {
682 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
683 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
684 }
687 lzma_set_size() {
688 # Update size field for lzma'd file packed using -si switch
689 return # Need to fix kernel code?
691 local n i
692 n=$(unlzma < $1 | wc -c)
693 for i in $(seq 1 8); do
694 printf '\\\\x%02X' $(($n & 255))
695 n=$(($n >> 8))
696 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
697 }
700 align_to_32bits() {
701 local size=$(stat -c %s ${1:-/dev/null})
702 [ $((${size:-0} & 3)) -ne 0 ] &&
703 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
704 }
707 dogzip() {
708 gzip -9 > $1
709 [ -x /usr/bin/advdef ] && advdef -qz4 $1
710 }
713 # Pack rootfs
715 pack_rootfs() {
716 ( cd $1; find . -print | cpio -o -H newc ) | \
717 case "$COMPRESSION" in
718 none)
719 _ 'Creating %s without compression...' 'initramfs'
720 cat > $2
721 ;;
722 gzip)
723 _ 'Creating %s with gzip compression...' 'initramfs'
724 dogzip $2
725 ;;
726 *)
727 _ 'Creating %s with lzma compression...' 'initramfs'
728 lzma e -si -so $(lzma_switches $1) > $2
729 lzma_set_size $2
730 ;;
731 esac
732 align_to_32bits $2
733 echo 1 > /tmp/rootfs
734 }
737 # Compression functions for writeiso.
739 write_initramfs() {
740 case "$COMPRESSION" in
741 lzma)
742 _n 'Creating %s with lzma compression...' "$INITRAMFS"
743 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
744 align='y'
745 lzma_set_size "/$INITRAMFS"
746 ;;
747 gzip)
748 _ 'Creating %s with gzip compression...' "$INITRAMFS"
749 cpio -o -H newc | dogzip "/$INITRAMFS"
750 ;;
751 *)
752 # align='y'
753 _ 'Creating %s without compression...' "$INITRAMFS"
754 cpio -o -H newc > "/$INITRAMFS"
755 ;;
756 esac < /tmp/list
757 [ "$align" == 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
758 echo 1 > /tmp/rootfs
759 }
762 # Deduplicate files (MUST be on the same filesystem).
764 deduplicate() {
765 find "${@:-.}" -type f -size +0c -xdev -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
766 (
767 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
768 while read attr inode link file; do
769 [ -L "$file" ] && continue
770 if [ "$attr" == "$old_attr" -a "$inode" != "$old_inode" ]; then
771 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
772 rm -f "$file"
773 if ln "$old_file" "$file" 2>/dev/null; then
774 inode="$old_inode"
775 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
776 save="$(($save+(${attr%%-*}+512)/1024))"
777 else
778 cp -a "$old_file" "$file"
779 fi
780 fi
781 fi
782 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
783 done
784 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
785 )
787 find "$@" -type l -xdev -exec stat -c '%s-%u-%g-TARGET- %i %h %n' {} \; | sort | \
788 (
789 old_attr=""; hardlinks=0;
790 while read attr inode link file; do
791 attr="${attr/-TARGET-/-$(readlink $file)}"
792 if [ "$attr" == "$old_attr" ]; then
793 if [ "$inode" != "$old_inode" ]; then
794 rm -f "$file"
795 if ln "$old_file" "$file" 2>/dev/null; then
796 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
797 else
798 cp -a "$old_file" "$file"
799 fi
800 fi
801 else
802 old_file="$file"
803 old_attr="$attr"
804 old_inode="$inode"
805 fi
806 done
807 _ '%s duplicate symlinks.' "$hardlinks"
808 )
809 }
812 # Generate a new initramfs from the root filesystem.
814 gen_initramfs() {
815 # Just in case CTRL+c
816 rm -f $DISTRO/gen
818 # Some packages may want to alter rootfs
819 genisohooks rootfs
820 cd $1
822 # Normalize file time
823 find $1 -newer $1 -exec touch -hr $1 {} \;
825 # Link duplicate files
826 deduplicate
828 # Use lzma if installed. Display rootfs size in realtime.
829 rm -f /tmp/rootfs 2>/dev/null
830 pack_rootfs . $DISTRO/$(basename $1).gz &
831 sleep 2
832 echo -en "\nFilesystem size:"
833 while [ ! -f /tmp/rootfs ]; do
834 sleep 1
835 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
836 done
837 echo -e "\n"
838 rm -f /tmp/rootfs
839 cd $DISTRO
840 mv $(basename $1).gz $ROOTCD/boot
841 }
844 distro_sizes() {
845 if [ -n "$start_time" ]; then
846 time=$(($(date +%s) - $start_time))
847 sec=$time
848 div=$(( ($time + 30) / 60))
849 [ "$div" -ne 0 ] && min="~ ${div}m"
850 _ 'Build time : %ss %s' "$sec" "$min"
851 fi
852 cat <<EOT
853 Build date : $(date +%Y%m%d)
854 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
855 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
856 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
857 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
858 EOT
859 footer "Image is ready: $ISO_NAME.iso"
860 }
863 # Print ISO and rootfs size.
865 distro_stats() {
866 title 'Distro statistics: %s' "$DISTRO"
867 distro_sizes
868 }
871 # Create an empty configuration file.
873 empty_config_file() {
874 cat >> tazlito.conf <<"EOF"
875 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
876 #
878 # Name of the ISO image to generate.
879 ISO_NAME=""
881 # ISO image volume name.
882 VOLUM_NAME="SliTaz"
884 # Name of the preparer.
885 PREPARED="$USER"
887 # Path to the packages repository and the packages.list.
888 PACKAGES_REPOSITORY=""
890 # Path to the distro tree to gen-distro from a list of packages.
891 DISTRO=""
893 # Path to the directory containing additional files
894 # to copy into the rootfs and rootcd of the LiveCD.
895 ADDFILES="$DISTRO/addfiles"
897 # Default answer for binary question (Y or N)
898 DEFAULT_ANSWER="ASK"
900 # Compression utility (lzma, gzip or none)
901 COMPRESSION="lzma"
902 EOF
903 }
906 # Extract rootfs.gz somewhere
908 extract_rootfs() {
909 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
910 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
911 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
912 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
913 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
914 }
917 # Extract flavor file to temp directory
919 extract_flavor() {
920 # Input: $1 - flavor name to extract;
921 # $2 = absent/empty: just extract 'outer layer'
922 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
923 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
924 # Output: temp dir path where flavor was extracted
925 local f="$1.flavor" from to infos="$1.desc"
926 [ -f "$f" ] || die "File '$f' not found"
927 local dir="$(mktemp -d)"
928 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
930 if [ -n "$2" ]; then
931 cd $dir
933 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
935 for i in rootcd rootfs; do
936 [ -f "$1.$i" ] || continue
937 mkdir "$i"
938 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
939 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
940 rm "$1.$i"
941 done
942 touch -t 197001010100.00 $1.*
943 # Info to be stored inside ISO
944 [ "$2" == info ] && echo -e $infos | cpio -o -H newc | dogzip info
945 rm $1.list*
947 # Renames
948 while read from to; do
949 [ -f "$from" ] || continue
950 mv "$from" "$to"
951 done <<EOT
952 $1.nonfree non-free.list
953 $1.pkglist packages.list
954 $1-distro.sh distro.sh
955 $1.receipt receipt
956 $1.mirrors mirrors
957 $1.desc description
958 EOT
959 fi
961 echo $dir
962 }
965 # Pack flavor file from temp directory
967 pack_flavor() {
968 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
969 }
972 # Remove duplicate files
974 files_match() {
975 if [ -d "$1" ]; then
976 return 1
978 elif [ -L "$1" ] && [ -L "$2" ]; then
979 [ "$(readlink "$1")" == "$(readlink "$2")" ] && return 0
981 elif [ -f "$1" ] && [ -f "$2" ]; then
982 cmp -s "$1" "$2" && return 0
984 [ "$(basename "$3")" == 'volatile.cpio.gz' ] &&
985 [ "$(dirname $(dirname "$3"))" == ".$INSTALLED" ] &&
986 return 0
988 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" == \
989 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
990 return 0
992 fi 2> /dev/null
993 return 1
994 }
996 remove_with_path() {
997 dir="$(dirname $1)"
998 rm -f "$1"
999 while rmdir "$dir" 2> /dev/null; do
1000 dir="$(dirname $dir)"
1001 done
1004 mergefs() {
1005 # Note, many packages have files with spaces in the name
1006 IFS=$'\n'
1008 local size1=$(du -hs "$1" | awk '{ print $1 }')
1009 local size2=$(du -hs "$2" | awk '{ print $1 }')
1010 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1012 # merge symlinks files and devices
1013 ( cd "$1"; find ) | \
1014 while read file; do
1015 files_match "$1/$file" "$2/$file" "$file" &&
1016 remove_with_path "$2/$file"
1017 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1018 done
1020 unset IFS
1021 status
1025 cleanup_merge() {
1026 rm -rf $TMP_DIR
1027 exit 1
1031 # Update isolinux config files for multiple rootfs
1033 update_bootconfig() {
1034 local files
1035 action 'Updating boot config files...'
1036 files="$(grep -l 'include common' $1/*.cfg)"
1037 for file in $files; do
1038 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1039 if (/label/) label=$0;
1040 else if (/kernel/) kernel=$0;
1041 else if (/append/) {
1042 i=index($0,"rootfs.gz");
1043 append=substr($0,i+9);
1045 else if (/include/) {
1046 for (i = 1; i <= n; i++) {
1047 print label i
1048 print kernel;
1049 initrd="initrd=/boot/rootfs" n ".gz"
1050 for (j = n - 1; j >= i; j--) {
1051 initrd=initrd ",/boot/rootfs" j ".gz";
1053 printf "\tappend %s%s\n",initrd,append;
1054 print "";
1056 print;
1058 else print;
1059 }' < $file > $file.$$
1060 mv -f $file.$$ $file
1061 done
1062 sel="$(echo $2 | awk '{
1063 for (i=1; i<=NF; i++)
1064 if (i % 2 == 0) printf " slitaz%d", i/2
1065 else printf " %s", $i
1066 }')"
1068 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1070 label slitaz
1071 kernel /boot/isolinux/ifmem.c32
1072 append$sel noram
1074 label noram
1075 config noram.cfg
1077 EOT
1079 # Update vesamenu
1080 if [ -s "$1/isolinux.cfg" ]; then
1081 files="$files $1/isolinux.cfg"
1082 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1083 BEGIN {
1084 kernel = " COM32 c32box.c32"
1087 if (/ROWS/) print "MENU ROWS " n+$3;
1088 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1089 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1090 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1091 else if (/VSHIFT/) {
1092 x = $3-n;
1093 if (x < 0) x = 0;
1094 print "MENU VSHIFT " x;
1096 else if (/rootfs.gz/) {
1097 linux = "";
1098 if (/bzImage/) linux = "linux /boot/bzImage ";
1099 i = index($0, "rootfs.gz");
1100 append = substr($0, i+9);
1101 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1102 printf "\tappend%s noram\n", sel;
1103 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1104 for (i = 1; i <= n; i++) {
1105 print "LABEL slitaz" i
1106 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1107 printf "%s\n", kernel;
1108 initrd = "initrd=/boot/rootfs" n ".gz"
1109 for (j = n - 1; j >= i; j--) {
1110 initrd = initrd ",/boot/rootfs" j ".gz";
1112 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1115 else if (/bzImage/) kernel = $0;
1116 else print;
1117 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1118 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1119 fi
1121 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1122 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1123 cat > $1/noram.cfg <<EOT
1124 implicit 0
1125 prompt 1
1126 timeout 80
1127 $(grep '^F[0-9]' $1/isolinux.cfg)
1129 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1130 say Not enough RAM to boot slitaz. Trying hacker mode...
1131 default hacker
1132 label hacker
1133 KERNEL /boot/bzImage
1134 append rw root=/dev/null vga=normal
1136 label reboot
1137 EOT
1139 if [ -s $1/c32box.c32 ]; then
1140 cat >> $1/noram.cfg <<EOT
1141 COM32 c32box.c32
1142 append reboot
1144 label poweroff
1145 COM32 c32box.c32
1146 append poweroff
1148 EOT
1149 else
1150 echo " com32 reboot.c32" >> $1/noram.cfg
1151 fi
1153 # Restore real label names
1154 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1155 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1156 while read pat; do
1157 sed -i "s/slitaz$pat/" $files
1158 done
1159 status
1163 # Uncompress rootfs or module to stdout
1165 uncompress() {
1166 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1167 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1171 # Install a missing package
1173 install_package() {
1174 if [ -z "$2" ]; then
1175 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1176 else
1177 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1178 fi
1179 case "$answer" in
1180 y)
1181 # We don't want package on host cache.
1182 action 'Getting and installing package: %s' "$1"
1183 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1184 status ;;
1185 *)
1186 return 1 ;;
1187 esac
1191 # Check iso for loram transformation
1193 check_iso_for_loram() {
1194 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1195 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1199 # Build initial rootfs for loram ISO ram/cdrom/http
1201 build_initfs() {
1202 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1203 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1204 mirror3.slitaz.org mirror.slitaz.org"
1205 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1206 [ -z "$version" ] && die "Can't find the kernel version." \
1207 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1209 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1210 need_lib=false
1211 for i in bin dev run mnt proc tmp sys lib/modules; do
1212 mkdir -p $TMP_DIR/initfs/$i
1213 done
1214 ln -s bin $TMP_DIR/initfs/sbin
1215 ln -s . $TMP_DIR/initfs/usr
1216 for aufs in aufs overlayfs; do
1217 [ -f /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z ] && break
1218 install_package linux-$aufs $version && break
1219 install_package $aufs $version && break
1220 done || return 1
1221 [ -s /init ] || install_package slitaz-boot-scripts
1222 cp /init $TMP_DIR/initfs/
1223 cp /lib/modules/$version/kernel/fs/$aufs/$aufs.ko.?z \
1224 $TMP_DIR/initfs/lib/modules
1225 if [ "$1" == 'cdrom' ]; then
1226 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1227 else
1228 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1229 while [ ! -f /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z ]; do
1230 install_package linux-squashfs $version || return 1
1231 done
1232 cp /lib/modules/$version/kernel/fs/squashfs/squashfs.ko.?z \
1233 $TMP_DIR/initfs/lib/modules
1234 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1235 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1236 fi
1237 if [ "$1" == 'http' ]; then
1238 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1239 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1240 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1241 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1242 cp -a /dev/fuse $TMP_DIR/initfs/dev
1243 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1244 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1245 else
1246 need_lib=true
1247 fi
1248 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1249 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1250 else
1251 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1252 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1253 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1254 cp -a /lib/librt* $TMP_DIR/initfs/lib
1255 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1256 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1257 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1258 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1259 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1260 need_lib=true
1261 fi
1262 cd $TMP_DIR/fs
1263 echo 'Getting slitaz-release & ethernet modules...'
1264 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1265 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1266 [ -s rootfs* ] || continue
1267 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1268 rm -f rootfs*
1269 done 2>&1 > /dev/null
1270 cd - > /dev/null
1271 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1272 find $TMP_DIR/fs/lib/modules/*/kernel/drivers/net/ethernet \
1273 -type f -name '*.ko*' | while read mod; do
1274 f=$TMP_DIR/initfs/lib/modules/$(basename $mod | sed s/..z$//)
1275 uncompress $mod > $f
1276 grep -q alias=pci: $f || rm -f $f
1277 done
1278 for i in $TMP_DIR/initfs/lib/modules/*.ko ; do
1279 f=$(basename $i)..z
1280 grep -q $f:$ $TMP_DIR/fs/lib/modules/*/modules.dep && continue
1281 deps="$(grep $f: $TMP_DIR/fs/lib/modules/*/modules.dep | sed 's/.*: //')"
1282 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > $TMP_DIR/initfs/lib/modules/$(basename $i .ko).dep
1283 for j in $deps; do
1284 mod=$(ls $TMP_DIR/fs/lib/modules/*/$j)
1285 uncompress $mod > $TMP_DIR/initfs/lib/modules/$(basename $j | sed s/..z$//)
1286 done
1287 done
1288 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"
1289 _n 'List of URLs to insert: '
1290 read -t 30 urliso2
1291 urliso="$urliso2 $urliso"
1292 fi
1293 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1294 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1295 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1296 else
1297 cp /bin/busybox $TMP_DIR/initfs/bin
1298 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1299 cp /sbin/insmod $TMP_DIR/initfs/bin
1300 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1301 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1302 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1303 fi
1304 need_lib=true
1305 fi
1306 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1307 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1308 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1309 done
1310 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1311 cp /lib/modules/$version/kernel/drivers/block/floppy.ko.?z \
1312 $TMP_DIR/initfs/lib/modules 2>/dev/null
1313 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1314 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1315 cp -a $i $TMP_DIR/initfs/dev
1316 done
1317 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1318 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1319 cp -a $i $TMP_DIR/initfs/dev
1320 done 2>/dev/null
1321 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1322 cp -a $i $TMP_DIR/initfs/lib
1323 done
1324 [ "$1" == 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1325 #!/bin/sh
1327 getarg() {
1328 grep -q " \$1=" /proc/cmdline || return 1
1329 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1330 return 0
1333 copy_rootfs() {
1334 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1335 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1336 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1337 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1338 path=/mnt/
1339 return 0
1340 else
1341 rm -f /mnt/rootfs*
1342 return 1
1343 fi
1346 echo "Switching / to tmpfs..."
1347 mount -t proc proc /proc
1348 size="\$(grep rootfssize= < /proc/cmdline | \\
1349 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1350 [ -n "\$size" ] || size="-o size=90%"
1352 mount -t sysfs sysfs /sys
1353 for i in /lib/modules/*.ko ; do
1354 echo -en "Probe \$i \\r"
1355 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1356 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1357 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1358 insmod /lib/modules/\$k.ko 2> /dev/null
1359 done
1360 echo "Loading \$i"
1361 insmod \$i 2> /dev/null
1362 break
1363 done
1364 done
1365 umount /sys
1366 while read var default; do
1367 eval \$var=\$default
1368 getarg \$var \$var
1369 done <<EOT
1370 eth eth0
1371 dns 208.67.222.222,208.67.220.220
1372 netmask 255.255.255.0
1373 gw
1374 ip
1375 EOT
1376 grep -q \$eth /proc/net/dev || sh
1377 if [ -n "\$ip" ]; then
1378 ifconfig \$eth \$ip netmask \$netmask up
1379 route add default gateway \$gw
1380 for i in \$(echo \$dns | sed 's/,/ /g'); do
1381 echo "nameserver \$i" >> /etc/resolv.conf
1382 done
1383 else
1384 udhcpc -f -q -s /lib/udhcpc -i \$eth
1385 fi
1386 for i in $urliso ; do
1387 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1388 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"
1389 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1390 done
1391 getarg urliso URLISO
1392 DIR=fs
1393 if getarg loram DIR; then
1394 DEVICE=\${DIR%,*}
1395 DIR=/\${DIR#*,}
1396 fi
1397 mount -t tmpfs \$size tmpfs /mnt
1398 path2=/mnt/.httpfs/
1399 path=/mnt/.cdrom/
1400 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1401 while [ ! -d \$path/boot ]; do
1402 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1403 httpfs \$i \$path2 && echo \$i && break
1404 done
1405 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1406 done
1408 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1409 umount /proc
1410 branch=:/mnt/.cdrom/\$DIR
1411 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1412 branch=
1413 lp=1
1414 insmod /lib/modules/squashfs.ko 2> /dev/null
1415 for i in \${path}boot/rootfs?.* ; do
1416 fs=\${i#*root}
1417 branch=\$branch:/mnt/.\$fs
1418 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1419 losetup -o 124 /dev/loop\$lp \$i
1420 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1421 lp=\$((\$lp+1))
1422 done
1423 fi
1424 mkdir -p /mnt/.rw/mnt/.httpfs
1425 while read type opt; do
1426 insmod /lib/modules/\$type.ko && mount -t \$type -o \$opt none /mnt && break
1427 done <<EOT
1428 aufs br=/mnt/.rw\$branch
1429 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1430 EOT
1431 rm -rf /lib/modules
1432 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1433 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1434 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1435 EOTEOT
1436 chmod +x $TMP_DIR/initfs/init
1437 for i in $TMP_DIR/initfs/lib/modules/*z ; do
1438 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1439 rm -f $i
1440 done 2>/dev/null
1441 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1442 lzma e $TMP_DIR/initfs.gz -si
1443 lzma_set_size $TMP_DIR/initfs.gz
1444 rm -rf $TMP_DIR/initfs
1445 align_to_32bits $TMP_DIR/initfs.gz
1446 return 0
1450 # Move each initramfs to squashfs
1452 build_loram_rootfs() {
1453 rootfs_sizes=""
1454 for i in $TMP_DIR/iso/boot/rootfs*; do
1455 mkdir -p $TMP_DIR/fs
1456 cd $TMP_DIR/fs
1457 uncompress $i | cpio -idm
1458 deduplicate
1459 cd - > /dev/null
1460 rootfs=$TMP_DIR/$(basename $i)
1461 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1462 cd $TMP_DIR
1463 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1464 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1465 rm -f $rootfs
1466 mv $rootfs.cpio $rootfs
1467 cd - > /dev/null
1468 rm -rf $TMP_DIR/fs
1469 done
1473 # Move meta boot configuration files to basic configuration files
1474 # because meta loram flavor is useless when rootfs is not loaded in RAM
1476 unmeta_boot() {
1477 local root=${1:-$TMP_DIR/loramiso}
1478 if [ -f $root/boot/isolinux/noram.cfg ]; then
1479 # We keep enough information to do unloram...
1480 [ -s $root/boot/isolinux/common.cfg ] &&
1481 sed -i 's/label slitaz/label orgslitaz/' \
1482 $root/boot/isolinux/common.cfg
1483 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1484 shift
1485 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1486 $root/boot/isolinux/isolinux.cfg
1487 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1488 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1489 $root/boot/isolinux/*.cfg
1490 fi
1494 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1495 # These squashfs may be loaded in RAM at boot time.
1496 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1497 # Meta flavors are converted to normal flavors.
1499 build_loram_cdrom() {
1500 build_initfs cdrom || return 1
1501 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1502 mkdir $TMP_DIR/loramiso/fs
1503 cd $TMP_DIR/loramiso/fs
1504 for i in $( ls ../boot/root* | sort -r ) ; do
1505 uncompress $i | cpio -idmu
1506 rm -f $i
1507 done
1508 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1509 cd - >/dev/null
1510 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1511 unmeta_boot
1512 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1513 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1514 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1515 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1516 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1517 create_iso $OUTPUT $TMP_DIR/loramiso
1521 # Create http bootstrap to load and remove loram_cdrom
1522 # Meta flavors are converted to normal flavors.
1524 build_loram_http() {
1525 build_initfs http || return 1
1526 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1527 rm -f $TMP_DIR/loramiso/boot/rootfs*
1528 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1529 unmeta_boot
1530 create_iso $OUTPUT $TMP_DIR/loramiso
1534 # Update meta flavor selection sizes.
1535 # Reduce sizes with rootfs gains.
1537 update_metaiso_sizes() {
1538 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1539 do
1540 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1541 local sizes="$rootfs_sizes"
1542 local new
1543 set -- $append
1544 shift
1545 [ "$1" == "ifmem" ] && shift
1546 new=""
1547 while [ -n "$2" ]; do
1548 local s
1549 case "$1" in
1550 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1551 *M) s=$(( ${1%M} * 1024 ));;
1552 *) s=${1%K};;
1553 esac
1554 sizes=${sizes#* }
1555 for i in $sizes ; do
1556 s=$(( $s - $i ))
1557 done
1558 new="$new $s $2"
1559 shift 2
1560 done
1561 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1562 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1563 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1564 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1565 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1566 done
1570 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1571 # Meta flavor selection sizes are updated.
1573 build_loram_ram() {
1574 build_initfs ram || return 1
1575 build_loram_rootfs "$1"
1576 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1577 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1578 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1579 update_metaiso_sizes
1580 create_iso $OUTPUT $TMP_DIR/loramiso
1584 # Remove files installed by packages
1586 find_flavor_rootfs() {
1587 for i in $1/etc/tazlito/*.extract; do
1588 [ -e $i ] || continue
1589 chroot $1 /bin/sh ${i#$1}
1590 done
1592 # Clean hardlinks and files patched by genisofs in /boot
1593 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1594 rm -f $1/boot/$i*
1595 done
1597 # Clean files generated in post_install
1598 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1599 $1/dev/core $1/dev/fd $1/dev/std*
1601 # Verify md5
1602 cat $1$INSTALLED/*/md5sum | \
1603 while read md5 file; do
1604 [ -e "$1$file" ] || continue
1605 [ "$(md5sum < "$1$file")" == "$md5 -" ] &&
1606 rm -f "$1$file"
1607 done
1609 # Check configuration files
1610 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1611 [ -e $i ] || continue
1612 mkdir /tmp/volatile$$
1613 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1614 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1615 while read file ; do
1616 [ -e "$1/$file" ] || continue
1617 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1618 done
1619 rm -rf /tmp/volatile$$
1620 done
1622 # Remove other files blindly
1623 for i in $1$INSTALLED/*/files.list; do
1624 for file in $(cat "$i"); do
1625 [ "$1$file" -nt "$i" ] && continue
1626 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1627 [ -d "$1$file" ] || rm -f "$1$file"
1628 done
1629 done
1631 # Remove tazpkg files and tmp files
1632 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1633 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1634 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1635 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1636 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1638 # Cleanup directory tree
1639 cd $1
1640 find * -type d | sort -r | while read dir; do
1641 rmdir "$dir" 2>/dev/null
1642 done
1643 cd - > /dev/null
1647 # Get byte(s) from a binary file
1649 get() {
1650 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1654 # Get cpio flavor info from the ISO image
1656 flavordata() {
1657 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1658 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1662 # Restore undigest mirrors
1664 restore_mirrors() {
1665 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1666 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1668 action 'Restoring mirrors...'
1669 if [ -d "$undigest.bak" ]; then
1670 [ -d "$undigest" ] && rm -r "$undigest"
1671 mv "$undigest.bak" "$undigest"
1672 fi
1673 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1674 :; status
1678 # Setup undigest mirrors
1680 setup_mirrors() {
1681 # Setup mirrors in plain system or in chroot (with variable root=)
1682 local mirrorlist="$1" fresh repacked
1683 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1685 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1686 restore_mirrors
1688 _ 'Setting up mirrors for %s...' "$root/"
1689 # Backing up current undigest mirrors and priority
1690 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1691 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1692 rm -rf '/var/www/tazlito/'
1693 mkdir -p '/var/www/tazlito/'
1695 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1696 fresh='/home/slitaz/packages'
1697 if [ -d "$fresh" ]; then
1698 # Setup first undigest mirror
1699 mkdir -p "$undigest/fresh"
1700 echo "$fresh" > "$undigest/fresh/mirror"
1701 echo 'fresh' >> "$priority"
1702 # Rebuild mirror DB if needed
1703 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1704 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1705 tazpkg mkdb "$fresh" --forced --root=''
1706 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1707 fi
1709 # Repacked packages: high priority
1710 repacked="$PACKAGES_REPOSITORY"
1711 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1712 # According to Tazlito setup file (tazlito.conf):
1713 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1714 # or
1715 # WORK_DIR="/home/slitaz"
1716 # and
1717 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1718 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1720 # Setup second undigest mirror
1721 mkdir -p "$undigest/repacked"
1722 echo "$repacked" > "$undigest/repacked/mirror"
1723 echo 'repacked' >> "$priority"
1724 # Rebuild mirror DB if needed
1725 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1726 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1727 tazpkg mkdb "$repacked" --forced --root=''
1728 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1729 fi
1731 # All repositories listed in mirrors list: normal priority
1732 [ -e "$mirrorlist" ] && \
1733 while read mirror; do
1734 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1735 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1736 mkdir -p "$undigest/$mirrorid"
1737 echo "$mirror" > "$undigest/$mirrorid/mirror"
1738 echo "$mirrorid" >> "$priority"
1739 done < "$mirrorlist"
1741 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1743 # Show list of mirrors
1744 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1745 function show(num, name, url) {
1746 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1749 num++;
1750 "cat " db "/undigest/" $0 "/mirror" | getline url;
1751 show(num, $0, url);
1753 END {
1754 num++;
1755 "cat " db "/mirror" | getline url;
1756 show(num, "main", url);
1757 }' "$priority"
1759 tazpkg recharge --quiet >/dev/null
1763 # Get list of 'packages.info' lists using priority
1765 pi_lists() {
1766 local pi
1767 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1768 local priority="$root$LOCALSTATE/priority"
1769 local undigest="$root$LOCALSTATE/undigest"
1772 [ -s "$priority" ] && cat "$priority"
1773 echo 'main'
1774 [ -d "$undigest" ] && ls "$undigest"
1775 } | awk -vun="$undigest/" '
1777 if (arr[$0] != 1) {
1778 arr[$0] = 1;
1779 print un $0 "/packages.info";
1781 }' | sed 's|/undigest/main||' | \
1782 while read pi; do
1783 [ -e "$pi" ] && echo "$pi"
1784 done
1788 # Strip versions from packages list
1790 strip_versions() {
1791 if [ -n "$stripped" ]; then
1792 action 'Consider list %s already stripped' "$(basename "$1")"
1793 status
1794 return 0
1795 fi
1796 action 'Strip versions from list %s...' "$(basename "$1")"
1797 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1798 [ -f "$in_list" ] || die "List '$in_list' not found."
1800 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1801 awk '
1803 if (FILENAME ~ "packages.info") {
1804 # Collect package names
1805 FS = "\t"; pkg[$1] = 1;
1806 } else {
1807 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1808 while (NF > 1 && ! pkg[$0])
1809 NF --;
1810 printf "%s\n", $0;
1812 }' $(pi_lists) "$in_list" > "$tmp_list"
1814 cat "$tmp_list" > "$in_list"
1815 rm "$tmp_list"
1816 status
1820 # Display list of unknown packages (informative)
1822 display_unknown() {
1823 [ -s "$1" ] || return
1824 echo "Unknown packages:" >&2
1825 cat "$1" >&2
1826 rm "$1"
1830 # Display warnings about critical packages absent (informative)
1832 display_warn() {
1833 [ -s "$1" ] || return
1834 echo "Absent critical packages:" >&2
1835 cat "$1" >&2
1836 rm "$1"
1837 echo "Probably ISO image will be unusable."
1841 # Install packages to rootfs
1843 install_list_to_rootfs() {
1844 local list="$1" rootfs="$2" pkg i ii
1845 local undigest="$rootfs/var/lib/tazpkg/undigest"
1847 # initial tazpkg setup in empty rootfs
1848 tazpkg --root=$rootfs >/dev/null 2>&1
1849 # pass current 'mirror' to the rootfs
1850 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1851 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1852 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1853 # link rootfs packages cache to the regular packages cache
1854 rm -r "$rootfs/var/cache/tazpkg"
1855 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1857 setup_mirrors mirrors
1859 # Just in case if flavor doesn't contain "tazlito" package
1860 mkdir -p "$rootfs/etc/tazlito"
1862 newline
1864 # Choose detailed log with --detailed
1865 if [ -n "$detailed" ]; then
1866 while read pkg; do
1867 separator '-'
1868 echo $pkg
1869 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
1870 done < $list
1871 separator '='
1872 else
1873 while read pkg; do
1874 action 'Installing package: %s' "$pkg"
1875 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
1876 status
1877 done < $list
1878 fi
1879 newline
1881 restore_mirrors
1882 # Remove 'fresh' and 'repacked' undigest repos leaving all other
1883 for i in fresh repacked; do
1884 ii="$undigest/$i"
1885 [ -d "$ii" ] && rm -rf "$ii"
1886 ii="$rootfs/var/lib/tazpkg/priority"
1887 if [ -f "$ii" ]; then
1888 sed -i "/$i/d" "$ii"
1889 [ -s "$ii" ] || rm "$ii"
1890 fi
1891 done
1892 [ -d "$undigest" ] && \
1893 for i in $(find "$undigest" -type f); do
1894 # Remove all undigest PKGDB files but 'mirror'
1895 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
1896 done
1897 [ -d "$undigest" ] && \
1898 rmdir --ignore-fail-on-non-empty "$undigest"
1900 # Un-link packages cache
1901 rm "$rootfs/var/cache/tazpkg"
1903 # Clean /var/lib/tazpkg
1904 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
1910 ####################
1911 # Tazlito commands #
1912 ####################
1914 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
1915 case "$0" in
1916 *reduplicate)
1917 find ${@:-.} ! -type d -links +1 \
1918 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
1919 exit 0 ;;
1920 *deduplicate)
1921 deduplicate "$@"
1922 exit 0 ;;
1923 esac
1926 case "$COMMAND" in
1927 stats)
1928 # Tazlito general statistics from the config file.
1930 title 'Tazlito statistics'
1931 optlist "\
1932 Config file : $CONFIG_FILE
1933 ISO name : $ISO_NAME.iso
1934 Volume name : $VOLUM_NAME
1935 Prepared : $PREPARED
1936 Packages repository : $PACKAGES_REPOSITORY
1937 Distro directory : $DISTRO
1938 Additional files : $ADDFILES
1939 " | sed '/: $/d'
1940 footer
1941 ;;
1944 list-addfiles)
1945 # Simple list of additional files in the rootfs
1946 newline
1947 if [ -d "$ADDFILES/rootfs" ]; then
1948 cd $ADDFILES
1949 find rootfs -type f
1950 else
1951 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
1952 fi
1953 newline
1954 ;;
1957 gen-config)
1958 # Generate a new config file in the current dir or the specified
1959 # directory by $2.
1961 if [ -n "$2" ]; then
1962 mkdir -p "$2" && cd "$2"
1963 fi
1965 newline
1966 action 'Generating empty tazlito.conf...'
1967 empty_config_file
1968 status
1970 separator
1971 if [ -f 'tazlito.conf' ] ; then
1972 _ 'Configuration file is ready to edit.'
1973 _ 'File location: %s' "$(pwd)/tazlito.conf"
1974 newline
1975 fi
1976 ;;
1979 configure)
1980 # Configure a tazlito.conf config file. Start by getting
1981 # a empty config file and sed it.
1983 if [ -f 'tazlito.conf' ]; then
1984 rm tazlito.conf
1985 else
1986 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
1987 'or in the same directory of the file you want to configure.'
1988 cd /etc
1989 fi
1991 empty_config_file
1993 title 'Configuring: %s' "$(pwd)/tazlito.conf"
1995 # ISO name.
1996 echo -n "ISO name : " ; read answer
1997 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
1998 # Volume name.
1999 echo -n "Volume name : " ; read answer
2000 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2001 # Packages repository.
2002 echo -n "Packages repository : " ; read answer
2003 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2004 # Distro path.
2005 echo -n "Distro path : " ; read answer
2006 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2007 footer "Config file is ready to use."
2008 echo 'You can now extract an ISO or generate a distro.'
2009 newline
2010 ;;
2013 gen-iso)
2014 # Simply generate a new iso.
2016 check_root
2017 verify_rootcd
2018 gen_livecd_isolinux
2019 distro_stats
2020 ;;
2023 gen-initiso)
2024 # Simply generate a new initramfs with a new iso.
2026 check_root
2027 verify_rootcd
2028 gen_initramfs "$ROOTFS"
2029 gen_livecd_isolinux
2030 distro_stats
2031 ;;
2034 extract-distro|extract-iso)
2035 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2037 check_root
2038 ISO_IMAGE="$2"
2039 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2040 'Example:\n tazlito image.iso /path/target'
2042 # Set the distro path by checking for $3 on cmdline.
2043 TARGET="${3:-$DISTRO}"
2045 # Exit if existing distro is found.
2046 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2047 'Please clean the distro tree or change directory path.'
2049 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2051 # Start to mount the ISO.
2052 action 'Mounting ISO image...'
2053 mkdir -p "$TMP_DIR"
2054 # Get ISO file size.
2055 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2056 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2057 sleep 2
2058 # Prepare target dir, copy the kernel and the rootfs.
2059 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2060 status
2062 action 'Copying the Linux kernel...'
2063 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2064 make_bzImage_hardlink "$TARGET/rootcd/boot"
2065 else
2066 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2067 fi
2068 status
2070 for i in $(ls $TMP_DIR); do
2071 [ "$i" == 'boot' ] && continue
2072 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2073 done
2075 for loader in isolinux syslinux extlinux grub; do
2076 [ -d "$TMP_DIR/boot/$loader" ] || continue
2077 action 'Copying %s files...' "$loader"
2078 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2079 status
2080 done
2082 action 'Copying the rootfs...'
2083 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2084 status
2086 # Extract initramfs.
2087 cd "$TARGET/rootfs"
2088 action 'Extracting the rootfs...'
2089 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2090 extract_rootfs "$i" "$TARGET/rootfs"
2091 done
2092 # unpack /usr
2093 for i in etc/tazlito/*.extract; do
2094 [ -f "$i" ] && . $i ../rootcd
2095 done
2096 # Umount and remove temp directory and cd to $TARGET to get stats.
2097 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2098 cd ..
2099 status
2101 newline
2102 separator
2103 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2104 echo "Distro tree : $(pwd)"
2105 echo "Rootfs size : $(du -sh rootfs)"
2106 echo "Rootcd size : $(du -sh rootcd)"
2107 footer
2108 ;;
2111 list-flavors)
2112 # Show available flavors.
2113 list='/etc/tazlito/flavors.list'
2114 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2115 title 'List of flavors'
2116 cat $list
2117 footer
2118 ;;
2121 show-flavor)
2122 # Show flavor descriptions.
2123 set -e
2124 flavor=${2%.flavor}
2125 flv_dir="$(extract_flavor "$flavor")"
2126 desc="$flv_dir/$flavor.desc"
2127 if [ -n "$brief" ]; then
2128 if [ -z "$noheader" ]; then
2129 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2130 separator
2131 fi
2132 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2133 "$(field ISO "$desc")" \
2134 "$(field Rootfs "$desc")" \
2135 "$(field Description "$desc")"
2136 else
2137 separator
2138 cat "$desc"
2139 fi
2140 cleanup
2141 ;;
2144 gen-liveflavor)
2145 # Generate a new flavor from the live system.
2146 FLAVOR=${2%.flavor}
2147 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2149 case "$FLAVOR" in
2150 -?|-h*|--help)
2151 cat <<EOT
2152 SliTaz Live Tool - Version: $VERSION
2154 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2156 $(boldify '<flavor-patch-file> format:')
2157 $(optlist "\
2158 code data
2159 + package to add
2160 - package to remove
2161 ! non-free package to add
2162 ? display message
2163 @ flavor description
2164 ")
2166 $(boldify 'Example:')
2167 $(optlist "\
2168 @ Developer tools for SliTaz maintainers
2169 + slitaz-toolchain
2170 + mercurial
2171 ")
2172 EOT
2173 exit 1
2174 ;;
2175 esac
2176 mv /etc/tazlito/distro-packages.list \
2177 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2178 rm -f distro-packages.list non-free.list 2>/dev/null
2179 tazpkg recharge
2181 DESC=""
2182 [ -n "$3" ] && \
2183 while read action pkg; do
2184 case "$action" in
2185 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2186 -) yes | tazpkg remove $pkg ;;
2187 !) echo $pkg >> non-free.list ;;
2188 @) DESC="$pkg" ;;
2189 \?) echo -en "$pkg"; read action ;;
2190 esac
2191 done < $3
2193 yes '' | tazlito gen-distro
2194 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2195 mv /etc/tazlito/distro-packages.list.$$ \
2196 /etc/tazlito/distro-packages.list 2>/dev/null
2197 ;;
2200 gen-flavor)
2201 # Generate a new flavor from the last ISO image generated
2202 FLAVOR=${2%.flavor}
2203 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2205 title 'Flavor generation'
2206 check_rootfs
2207 FILES="$FLAVOR.pkglist"
2209 action 'Creating file %s...' "$FLAVOR.flavor"
2210 for i in rootcd rootfs; do
2211 if [ -d "$ADDFILES/$i" ] ; then
2212 FILES="$FILES\n$FLAVOR.$i"
2213 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2214 fi
2215 done
2216 status
2218 answer=$(grep -s ^Description $FLAVOR.desc)
2219 answer=${answer#Description : }
2220 if [ -z "$answer" ]; then
2221 echo -n "Description: "
2222 read answer
2223 fi
2225 action 'Compressing flavor %s...' "$FLAVOR"
2226 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2227 echo "Description : $answer" >> $FLAVOR.desc
2228 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2229 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2230 for i in $(ls $ROOTFS$INSTALLED); do
2231 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2232 EXTRAVERSION=""
2233 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2234 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2235 if [ "$CATEGORY" == 'non-free' -a "${i%%-*}" != 'get' ]; then
2236 echo "$i" >> $FLAVOR.nonfree
2237 else
2238 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2239 fi
2240 done
2241 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2242 for i in $LOCALSTATE/undigest/*/mirror ; do
2243 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2244 done
2245 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2246 touch -t 197001010100.00 $FLAVOR.*
2247 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2248 rm $(echo -e $FILES)
2249 status
2251 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2252 ;;
2255 upgrade-flavor)
2256 # Strip versions from pkglist and update estimated numbers in flavor.desc
2257 flavor="${2%.flavor}"
2258 set -e
2259 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2260 set +e
2262 flv_dir="$(extract_flavor "$flavor")"
2264 strip_versions "$flv_dir/$flavor.pkglist"
2266 action 'Updating %s...' "$flavor.desc"
2268 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2269 set -- $(module calc_sizes "$flv_dir" "$flavor")
2270 restore_mirrors >/dev/null
2272 sed -i -e '/Image is ready/d' \
2273 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2274 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2275 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2276 -e "s|\(Packages *:\).*$|\1 $4|" \
2277 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2278 "$flv_dir/$flavor.desc"
2280 pack_flavor "$flv_dir" "$flavor"
2281 status
2282 display_unknown "$flv_dir/err"
2283 display_warn "$flv_dir/warn"
2284 cleanup
2285 ;;
2288 extract-flavor)
2289 # Extract a flavor into $FLAVORS_REPOSITORY
2290 flavor="${2%.flavor}"
2291 set -e
2292 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2293 set +e
2295 action 'Extracting %s...' "$flavor.flavor"
2296 flv_dir="$(extract_flavor "$flavor" full)"
2297 storage="$FLAVORS_REPOSITORY/$flavor"
2299 rm -rf "$storage" 2>/dev/null
2300 mkdir -p "$storage"
2301 cp -a "$flv_dir"/* "$storage"
2302 rm "$storage/description"
2303 status
2305 strip_versions "$storage/packages.list"
2307 cleanup
2308 ;;
2311 pack-flavor)
2312 # Create a flavor from $FLAVORS_REPOSITORY.
2313 flavor=${2%.flavor}
2314 storage="$FLAVORS_REPOSITORY/$flavor"
2316 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2318 action 'Creating flavor %s...' "$flavor"
2319 tmp_dir="$(mktemp -d)"
2321 while read from to; do
2322 [ -s "$storage/$from" ] || continue
2323 cp -a "$storage/$from" "$tmp_dir/$to"
2324 done <<EOT
2325 mirrors $flavor.mirrors
2326 distro.sh $flavor-distro.sh
2327 receipt $flavor.receipt
2328 non-free.list $flavor.nonfree
2329 EOT
2331 # Build the package list.
2332 # It can include a list from another flavor with the keyword @include
2333 if [ -s "$storage/packages.list" ]; then
2334 include=$(grep '^@include' "$storage/packages.list")
2335 if [ -n "$include" ]; then
2336 include=${include#@include }
2337 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2338 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2339 else
2340 echo -e "\nERROR: Can't find include package list from $include\n"
2341 fi
2342 fi
2343 # Generate the final/initial package list
2344 [ -s "$storage/packages.list" ] && \
2345 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2346 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2347 fi
2349 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2350 # Process multi-rootfs flavor
2351 . "$storage/receipt"
2352 set -- $ROOTFS_SELECTION
2353 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2354 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2355 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2357 for i in rootcd rootfs; do
2358 mkdir "$tmp_dir/$i"
2359 # Copy extra files from the first flavor
2360 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2361 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2362 # Overload extra files by meta flavor
2363 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2364 [ -n "$(ls $tmp_dir/$i)" ] &&
2365 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2366 dogzip "$tmp_dir/$flavor.$i"
2367 rm -rf "$tmp_dir/$i"
2368 done
2369 else
2370 # Process plain flavor
2371 for i in rootcd rootfs; do
2372 [ -d "$storage/$i" ] || continue
2373 (cd "$storage/$i";
2374 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2375 done
2376 fi
2378 unset VERSION MAINTAINER ROOTFS_SELECTION
2379 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2380 ROOTFS_SIZE="$1 (estimated)"
2381 INITRAMFS_SIZE="$2 (estimated)"
2382 ISO_SIZE="$3 (estimated)"
2383 PKGNUM="$4"
2384 . "$storage/receipt"
2386 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2387 Flavor : $FLAVOR
2388 Description : $SHORT_DESC
2389 Version : $VERSION
2390 Maintainer : $MAINTAINER
2391 LiveCD RAM size : $FRUGAL_RAM
2392 Rootfs list : $ROOTFS_SELECTION
2393 Build date : $(date '+%Y%m%d at %T')
2394 Packages : $PKGNUM
2395 Rootfs size : $ROOTFS_SIZE
2396 Initramfs size : $INITRAMFS_SIZE
2397 ISO image size : $ISO_SIZE
2398 ================================================================================
2400 EOT
2402 rm -f $tmp_dir/packages.list
2403 pack_flavor "$tmp_dir" "$flavor"
2404 status
2405 display_unknown "$tmp_dir/err"
2406 display_warn "$flv_dir/warn"
2407 cleanup
2408 ;;
2411 get-flavor)
2412 # Get a flavor's files and prepare for gen-distro.
2413 flavor=${2%.flavor}
2414 title 'Preparing %s distro flavor' "$flavor"
2415 set -e
2416 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2417 set +e
2419 action 'Cleaning %s...' "$DISTRO"
2420 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2421 # Clean old files
2422 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2423 [ -f "$i" ] && rm "$i"
2424 done
2425 mkdir -p "$DISTRO"
2426 status
2428 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2430 action 'Extracting flavor %s...' "$flavor.flavor"
2431 flv_dir="$(extract_flavor "$flavor" info)"
2432 cp -a "$flv_dir"/* .
2433 mv packages.list distro-packages.list
2434 mv -f info /etc/tazlito
2435 status
2437 for i in rootcd rootfs; do
2438 if [ -d "$i" ]; then
2439 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2440 fi
2441 done
2443 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2444 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2446 action 'Updating %s...' 'tazlito.conf'
2447 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2448 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2449 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2450 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2451 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2452 status
2454 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2455 cleanup
2456 ;;
2459 iso2flavor)
2460 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2461 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2463 FLAVOR=${3%.flavor}
2464 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2465 mount -o loop,ro $2 $TMP_DIR/iso
2466 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2467 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2468 ! -s $TMP_DIR/flavor/*.desc ]; then
2469 _ 'META flavors are not supported.'
2470 umount -d $TMP_DIR/iso
2471 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2472 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2473 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2474 umount -d $TMP_DIR/iso
2475 else
2476 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2477 uncompress $i | \
2478 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2479 done
2480 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2481 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2482 '/etc/slitaz-release' '/boot/rootfs.gz'
2483 umount -d $TMP_DIR/iso
2484 else
2485 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2486 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2487 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2488 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2489 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2490 umount -d $TMP_DIR/iso
2491 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2492 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2493 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2494 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2495 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2496 < $TMP_DIR/rootfs$INSTALLED.md5
2497 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2498 if [ -s $TMP_DIR/flavor/*desc ]; then
2499 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2500 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2501 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2502 for i in rootfs rootcd ; do
2503 [ -s $TMP_DIR/flavor/*.list$i ] &&
2504 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2505 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2506 done
2507 else
2508 find_flavor_rootfs $TMP_DIR/rootfs
2509 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2510 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2511 for i in rootfs rootcd ; do
2512 [ "$(ls $TMP_DIR/$i)" ] &&
2513 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2514 done
2515 unset VERSION MAINTAINER
2516 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2517 if [ -n "$DESCRIPTION" ]; then
2518 _n 'Flavor version : '; read -t 30 VERSION
2519 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2520 fi
2522 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2523 Flavor : $FLAVOR
2524 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2525 Version : ${VERSION:-1.0}
2526 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2527 LiveCD RAM size : $RAM_SIZE
2528 Build date : $BUILD_DATE
2529 Packages : $PKGCNT
2530 Rootfs size : $ROOTFS_SIZE
2531 Initramfs size : $INITRAMFS_SIZE
2532 ISO image size : $ISO_SIZE
2533 ================================================================================
2535 EOT
2536 longline "Tazlito can't detect each file installed during \
2537 a package post_install. You should extract this flavor (tazlito extract-flavor \
2538 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2539 tree and remove files generated by post_installs.
2540 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2541 repack the flavor (tazlito pack-flavor $FLAVOR)"
2542 fi
2543 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2544 fi
2545 fi
2546 rm -rf $TMP_DIR
2547 ;;
2550 gen-distro)
2551 # Generate a live distro tree with a set of packages.
2553 check_root
2554 start_time=$(date +%s)
2556 # Tazlito options: --iso or --cdrom
2557 CDROM=''
2558 [ -n "$iso" ] && CDROM="-o loop $iso"
2559 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2561 # Check if a package list was specified on cmdline.
2562 if [ -f "$2" ]; then
2563 LIST_NAME="$2"
2564 else
2565 LIST_NAME='distro-packages.list'
2566 fi
2568 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2569 'Please clean the distro tree or change directory path.'
2570 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2571 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2573 # If list not given: build list with all installed packages
2574 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2575 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2576 fi
2578 # Exit if no list name.
2579 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2581 # Start generation.
2582 title 'Tazlito generating a distro'
2584 # Misc checks
2585 mkdir -p "$PACKAGES_REPOSITORY"
2586 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2587 newline
2589 # Mount CD-ROM to be able to repack boot-loader packages
2590 if [ ! -e /boot -a -n "$CDROM" ]; then
2591 mkdir $TMP_MNT
2592 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2593 ln -s "$TMP_MNT/boot" /
2594 if [ ! -d "$ADDFILES/rootcd" ] ; then
2595 mkdir -p "$ADDFILES/rootcd"
2596 for i in $(ls $TMP_MNT); do
2597 [ "$i" == 'boot' ] && continue
2598 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2599 done
2600 fi
2601 else
2602 rmdir "$TMP_MNT"
2603 fi
2604 fi
2606 # Rootfs stuff.
2607 echo 'Preparing the rootfs directory...'
2608 mkdir -p "$ROOTFS"
2609 export root="$ROOTFS"
2610 # pass current 'mirror' to the root
2611 mkdir -p $root/var/lib/tazpkg $root/etc
2612 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2613 cp -f /etc/slitaz-release $root/etc/slitaz-release
2614 strip_versions "$LIST_NAME"
2616 if [ "$REPACK" == 'y' ]; then
2617 # Determine full packages list with all dependencies
2618 tmp_dir="$(mktemp -d)"
2619 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2620 touch "$tmp_dir/full.pkglist"
2621 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2623 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2624 while read pkgname pkgver; do
2625 # Is package in full list?
2626 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2627 # Is package already repacked?
2628 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2629 _ 'Repacking %s...' "$pkgname-$pkgver"
2630 tazpkg repack "$pkgname" --quiet
2631 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2632 status
2633 done
2635 rm -r "$tmp_dir"
2636 fi
2638 if [ -f non-free.list ]; then
2639 # FIXME: working in the ROOTFS chroot?
2640 newline
2641 echo 'Preparing non-free packages...'
2642 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2643 for pkg in $(cat 'non-free.list'); do
2644 if [ ! -d "$INSTALLED/$pkg" ]; then
2645 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2646 tazpkg get-install get-$pkg
2647 fi
2648 get-$pkg "$ROOTFS"
2649 fi
2650 tazpkg repack $pkg
2651 pkg=$(ls $pkg*.tazpkg)
2652 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2653 mv $pkg $PACKAGES_REPOSITORY
2654 done
2655 fi
2656 cp $LIST_NAME $DISTRO/distro-packages.list
2657 newline
2659 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2661 cd $DISTRO
2662 cp distro-packages.list $ROOTFS/etc/tazlito
2663 # Copy all files from $ADDFILES/rootfs to the rootfs.
2664 if [ -d "$ADDFILES/rootfs" ] ; then
2665 action 'Copying addfiles content to the rootfs...'
2666 cp -a $ADDFILES/rootfs/* $ROOTFS
2667 status
2668 fi
2670 action 'Root filesystem is generated...'; status
2672 # Root CD part.
2673 action 'Preparing the rootcd directory...'
2674 mkdir -p $ROOTCD
2675 status
2677 # Move the boot dir with the Linux kernel from rootfs.
2678 # The efi & boot dirs go directly on the CD.
2679 if [ -d "$ROOTFS/efi" ] ; then
2680 action 'Moving the efi directory...'
2681 mv $ROOTFS/efi $ROOTCD
2682 status
2683 fi
2684 if [ -d "$ROOTFS/boot" ] ; then
2685 action 'Moving the boot directory...'
2686 mv $ROOTFS/boot $ROOTCD
2687 status
2688 fi
2689 cd $DISTRO
2690 # Copy all files from $ADDFILES/rootcd to the rootcd.
2691 if [ -d "$ADDFILES/rootcd" ] ; then
2692 action 'Copying addfiles content to the rootcd...'
2693 cp -a $ADDFILES/rootcd/* $ROOTCD
2694 status
2695 fi
2696 # Execute the distro script used to perform tasks in the rootfs
2697 # before compression. Give rootfs path in arg
2698 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2699 if [ -x "$DISTRO_SCRIPT" ]; then
2700 echo 'Executing distro script...'
2701 sh $DISTRO_SCRIPT $DISTRO
2702 fi
2704 # Execute the custom_rules() found in receipt.
2705 if [ -s "$TOP_DIR/receipt" ]; then
2706 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2707 echo -e "Executing: custom_rules()\n"
2708 . "$TOP_DIR/receipt"
2709 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2710 fi
2711 fi
2713 # Multi-rootfs
2714 if [ -s /etc/tazlito/rootfs.list ]; then
2716 FLAVOR_LIST="$(awk '{
2717 for (i = 2; i <= NF; i+=2)
2718 printf "%s ", $i;
2719 }' /etc/tazlito/rootfs.list)"
2721 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2722 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2723 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2725 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2726 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2727 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2728 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2730 n=0
2731 last=$ROOTFS
2732 while read flavor; do
2733 n=$(($n+1))
2734 mkdir ${ROOTFS}0$n
2735 export root="${ROOTFS}0$n"
2736 # initial tazpkg setup in empty rootfs
2737 tazpkg --root=$root >/dev/null 2>&1
2739 newline
2740 boldify "Building $flavor rootfs..."
2742 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2743 cp "$TOP_DIR/$flavor.flavor" .
2745 if [ ! -s "$flavor.flavor" ]; then
2746 # We may have it in $FLAVORS_REPOSITORY
2747 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2748 tazlito pack-flavor $flavor
2749 else
2750 download $flavor.flavor
2751 fi
2752 fi
2754 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2755 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2756 cp $flavor.pkglist $DISTRO/list-packages0$n
2757 status
2759 strip_versions "$DISTRO/list-packages0$n"
2761 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2763 action 'Updating the boot directory...'
2764 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2765 rm -rf ${ROOTFS}0$n/boot
2767 cd $DISTRO
2768 if [ -s $flavor.rootfs ]; then
2769 _n 'Adding %s rootfs extra files...' "$flavor"
2770 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2771 fi
2773 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2774 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2775 status
2777 rm -f $flavor.flavor install-list
2778 mergefs ${ROOTFS}0$n $last
2779 last=${ROOTFS}0$n
2780 done <<EOT
2781 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2782 EOT
2783 #'
2784 i=$(($n+1))
2785 while [ $n -gt 0 ]; do
2786 mv ${ROOTFS}0$n ${ROOTFS}$i
2787 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2788 gen_initramfs ${ROOTFS}$i
2789 n=$(($n-1))
2790 i=$(($i-1))
2791 export LZMA_HISTORY_BITS=26
2792 done
2793 mv $ROOTFS ${ROOTFS}$i
2794 gen_initramfs ${ROOTFS}$i
2795 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2796 ROOTFS=${ROOTFS}1
2797 else
2798 # Initramfs and ISO image stuff.
2799 gen_initramfs $ROOTFS
2800 fi
2801 gen_livecd_isolinux
2802 distro_stats
2803 cleanup
2804 ;;
2807 clean-distro)
2808 # Remove old distro tree.
2810 check_root
2811 title 'Cleaning: %s' "$DISTRO"
2812 if [ -d "$DISTRO" ] ; then
2813 if [ -d "$ROOTFS" ] ; then
2814 action 'Removing the rootfs...'
2815 rm -f $DISTRO/$INITRAMFS
2816 rm -rf $ROOTFS
2817 status
2818 fi
2819 if [ -d "$ROOTCD" ] ; then
2820 action 'Removing the rootcd...'
2821 rm -rf $ROOTCD
2822 status
2823 fi
2824 action 'Removing eventual ISO image...'
2825 rm -f $DISTRO/$ISO_NAME.iso
2826 rm -f $DISTRO/$ISO_NAME.md5
2827 status
2828 fi
2829 footer
2830 ;;
2833 check-distro)
2834 # Check for a few LiveCD needed files not installed by packages.
2836 # TODO: Remove this function.
2837 # First two files are maintained by tazpkg while it runs on rootfs,
2838 # while last one file should be maintained by tazlito itself.
2839 check_rootfs
2840 title 'Checking distro: %s' "$ROOTFS"
2841 # SliTaz release info.
2842 rel='/etc/slitaz-release'
2843 if [ ! -f "$ROOTFS$rel" ]; then
2844 _ 'Missing release info: %s' "$rel"
2845 else
2846 action 'Release : %s' "$(cat $ROOTFS$rel)"
2847 status
2848 fi
2849 # Tazpkg mirror.
2850 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2851 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2852 todomsg
2853 else
2854 action 'Mirror configuration exists...'
2855 status
2856 fi
2857 # Isolinux msg
2858 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2859 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2860 todomsg
2861 else
2862 action 'Isolinux message seems good...'
2863 status
2864 fi
2865 footer
2866 ;;
2869 writeiso)
2870 # Writefs to ISO image including /home unlike gen-distro we don't use
2871 # packages to generate a rootfs, we build a compressed rootfs with all
2872 # the current filesystem similar to 'tazusb writefs'.
2874 DISTRO='/home/slitaz/distro'
2875 ROOTCD="$DISTRO/rootcd"
2876 COMPRESSION="${2:-none}"
2877 ISO_NAME="${3:-slitaz}"
2878 check_root
2879 # Start info
2880 title 'Write filesystem to ISO'
2881 longline "The command writeiso will write the current filesystem into a \
2882 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
2883 newline
2884 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
2886 [ "$COMPRESSION" == 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
2887 # Save some space
2888 rm -rf /var/cache/tazpkg/*
2889 rm -f /var/lib/tazpkg/*.bak
2890 rm -rf $DISTRO
2892 # Optionally remove sound card selection and screen resolution.
2893 if [ -z $LaunchedByTazpanel ]; then
2894 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
2895 case $anser in
2896 y)
2897 action 'Removing current sound card and screen configurations...'
2898 rm -f /var/lib/sound-card-driver
2899 rm -f /var/lib/alsa/asound.state
2900 rm -f /etc/X11/xorg.conf ;;
2901 *)
2902 action 'Keeping current sound card and screen configurations...' ;;
2903 esac
2904 status
2905 newline
2907 # Optionally remove i18n settings
2908 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
2909 case $anser in
2910 y)
2911 action 'Removing current locale/keymap settings...'
2912 newline > /etc/locale.conf
2913 newline > /etc/keymap.conf ;;
2914 *)
2915 action 'Keeping current locale/keymap settings...' ;;
2916 esac
2917 status
2918 fi
2920 # Clean-up files by default
2921 newline > /etc/udev/rules.d/70-persistent-net.rules
2922 newline > /etc/udev/rules.d/70-persistant-cd.rules
2924 # Create list of files including default user files since it is defined in /etc/passwd
2925 # and some new users might have been added.
2926 cd /
2927 echo 'init' > /tmp/list
2928 for dir in bin etc sbin var dev lib root usr home opt; do
2929 [ -d $dir ] && find $dir
2930 done >> /tmp/list
2932 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
2933 [ -d $dir ] && echo $dir
2934 done >> /tmp/list
2936 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
2938 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
2939 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
2940 #fi
2941 mv -f /var/log/wtmp /tmp/tazlito-wtmp
2942 touch /var/log/wtmp
2944 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
2945 sed -i "/var\/log\/$removelog/d" /tmp/list
2946 done
2948 # Generate initramfs with specified compression and display rootfs
2949 # size in realtime.
2950 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
2952 write_initramfs &
2953 sleep 2
2954 cd - > /dev/null
2955 echo -en "\nFilesystem size:"
2956 while [ ! -f /tmp/rootfs ]; do
2957 sleep 1
2958 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
2959 done
2960 mv -f /tmp/tazlito-wtmp /var/log/wtmp
2961 echo -e "\n"
2962 rm -f /tmp/rootfs
2964 # Move freshly generated rootfs to the cdrom.
2965 mkdir -p $ROOTCD/boot
2966 mv -f /$INITRAMFS $ROOTCD/boot
2967 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
2969 # Now we need the kernel and isolinux files.
2970 copy_from_cd() {
2971 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
2972 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
2973 unmeta_boot $ROOTCD
2974 umount /media/cdrom
2977 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
2978 copy_from_cd;
2979 elif mount | grep /media/cdrom; then
2980 copy_from_cd;
2981 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
2982 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
2983 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
2984 else
2985 touch /tmp/.write-iso-error
2986 longline "When SliTaz is running in RAM the kernel and bootloader \
2987 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
2988 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
2989 echo -en "----\nENTER to continue..."; read i
2990 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
2991 copy_from_cd
2992 fi
2994 # Generate the iso image.
2995 touch /tmp/.write-iso
2996 newline
2997 cd $DISTRO
2998 create_iso $ISO_NAME.iso $ROOTCD
2999 action 'Creating the ISO md5sum...'
3000 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3001 status
3003 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3004 rm -f /tmp/.write-iso
3006 if [ -z $LaunchedByTazpanel ]; then
3007 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3008 case $anser in
3009 y)
3010 umount /dev/cdrom 2>/dev/null
3011 eject
3012 echo -n "Please insert a blank CD-ROM and press ENTER..."
3013 read i && sleep 2
3014 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3015 echo -en "----\nENTER to continue..."; read i ;;
3016 *)
3017 exit 0 ;;
3018 esac
3019 fi
3020 ;;
3023 burn-iso)
3024 # Guess CD-ROM device, ask user and burn the ISO.
3026 check_root
3027 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3028 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3029 # We can specify an alternative ISO from the cmdline.
3030 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3031 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3033 title 'Tazlito burn ISO'
3034 echo "CD-ROM device : /dev/$DRIVE_NAME"
3035 echo "Drive speed : $DRIVE_SPEED"
3036 echo "ISO image : $iso"
3037 footer
3039 case $(yesorno 'Burn ISO image?' 'n') in
3040 y)
3041 title 'Starting Wodim to burn the ISO...'
3042 sleep 2
3043 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3044 footer 'ISO image is burned to CD-ROM.'
3045 ;;
3046 *)
3047 die 'Exiting. No ISO burned.'
3048 ;;
3049 esac
3050 ;;
3053 merge)
3054 # Merge multiple rootfs into one iso.
3056 if [ -z "$2" ]; then
3057 cat <<EOT
3058 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3060 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3061 i.e: rootfsN is a subset of rootfsN-1
3062 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3063 The boot loader will select the rootfs according to the RAM size detected.
3065 Example:
3066 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3068 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3069 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3071 EOT
3072 exit 2
3073 fi
3075 shift # skip merge
3076 append="$1 slitaz1"
3077 shift # skip size1
3078 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3080 ISO=$1.merged
3082 # Extract filesystems
3083 action 'Mounting %s' "$1"
3084 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3085 status || cleanup_merge
3087 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3088 make_bzImage_hardlink $TMP_DIR/iso/boot
3089 umount -d $TMP_DIR/mnt
3090 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3091 _ '%s is already a merged iso. Aborting.' "$1"
3092 cleanup_merge
3093 fi
3094 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3095 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3096 if [ ! -f /boot/isolinux/ifmem.c32 -a
3097 ! -f /boot/isolinux/c32box.c32 ]; then
3098 cat <<EOT
3099 No file /boot/isolinux/ifmem.c32
3100 Please install syslinux package !
3101 EOT
3102 rm -rf $TMP_DIR
3103 exit 1
3104 fi
3105 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3106 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3107 fi
3109 action 'Extracting %s' 'iso/rootfs.gz'
3110 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3111 [ -d $TMP_DIR/rootfs1/etc ]
3112 status || cleanup_merge
3114 n=1
3115 while [ -n "$2" ]; do
3116 shift # skip rootfs N-1
3117 p=$n
3118 n=$(($n + 1))
3119 append="$append $1 slitaz$n"
3120 shift # skip size N
3121 mkdir -p $TMP_DIR/rootfs$n
3123 action 'Extracting %s' "$1"
3124 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3125 [ -d "$TMP_DIR/rootfs$n/etc" ]
3126 status || cleanup_merge
3128 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3129 action 'Creating %s' "rootfs$p.gz"
3130 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3131 status
3132 done
3133 action 'Creating %s' "rootfs$n.gz"
3134 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3135 status
3136 rm -f $TMP_DIR/iso/boot/rootfs.gz
3137 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3138 create_iso $ISO $TMP_DIR/iso
3139 rm -rf $TMP_DIR
3140 ;;
3143 repack)
3144 # Repack an iso with maximum lzma compression ratio.
3146 ISO=$2
3147 mkdir -p $TMP_DIR/mnt
3149 # Extract filesystems
3150 action 'Mounting %s' "$ISO"
3151 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3152 status || cleanup_merge
3154 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3155 umount -d $TMP_DIR/mnt
3157 for i in $TMP_DIR/iso/boot/rootfs* ; do
3158 action 'Repacking %s' "$(basename $i)"
3159 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3160 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3161 align_to_32bits $i
3162 status
3163 done
3165 create_iso $ISO $TMP_DIR/iso
3166 rm -rf $TMP_DIR
3167 ;;
3170 build-loram)
3171 # Build a Live CD for low RAM systems.
3173 ISO="$2"
3174 OUTPUT="$3"
3175 [ -z "$3" ] && \
3176 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3177 mkdir -p "$TMP_DIR/iso"
3178 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3179 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3180 if ! check_iso_for_loram ; then
3181 umount -d "$TMP_DIR/iso"
3182 die "$ISO is not a valid SliTaz live CD. Abort."
3183 fi
3184 case "$4" in
3185 cdrom) build_loram_cdrom ;;
3186 http) build_loram_http ;;
3187 *) build_loram_ram "$5" ;;
3188 esac
3189 umount $TMP_DIR/iso # no -d: needs /proc
3190 losetup -d $loopdev
3191 rm -rf $TMP_DIR
3192 ;;
3195 emu-iso)
3196 # Emulate an ISO image with Qemu.
3197 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3198 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3199 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3200 echo -e "\nStarting Qemu emulator:\n"
3201 echo -e "qemu $QEMU_OPTS $iso\n"
3202 qemu $QEMU_OPTS $iso
3203 ;;
3206 deduplicate)
3207 # Deduplicate files in a tree
3208 shift
3209 deduplicate "$@"
3210 ;;
3213 usage|*)
3214 # Print usage also for all unknown commands.
3215 usage
3216 ;;
3217 esac
3219 exit 0