tazlito view tazlito @ rev 515

Fix deduplicate symlinks
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu May 23 11:09:57 2019 +0200 (2019-05-23)
parents 7c8e4ca19511
children 06217db0ecc0
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 [ -x $2/boot/isolinux/efi.img ] && return
308 local n=$(get 19 "$2/boot/isolinux/efi.img")
309 [ $n -eq 0 ] && n=$(get 32 "$2/boot/isolinux/efi.img" 4)
310 efiblock=$(first_block "$2/boot/isolinux/efi.img")
311 fix_efi_img_size $(($n*512)) $1
312 fix_efi_boot_img_size $1 $2 $n $efiblock
314 # Build file list tree
315 resv=$(get 14 "$2/boot/isolinux/efi.img")
316 if [ $(get 57 "$2/boot/isolinux/efi.img" 1) -ne 49 ]; then
317 skiphead=5
318 fatsz=$(get 36 "$2/boot/isolinux/efi.img" 4)
319 basecluster=$((($resv+2*$fatsz)/4+$efiblock-2))
320 dd if=$1 bs=512 skip=$(($efiblock*4)) count=3 \
321 of=$1 seek=$(($efiblock*4+3)) conv=notrunc
322 else
323 skiphead=4
324 fatsz=$(get 22 "$2/boot/isolinux/efi.img")
325 basecluster=$((($resv+2*$fatsz)/4+$efiblock-1))
326 fi 2> /dev/null
327 hd "$2/boot/isolinux/efi.img" | awk 'BEGIN { skiphead='$skiphead' }
328 {
329 if (skiphead!=0) {
330 if ($1=="*") skiphead--
331 next
332 }
333 if (skipdot!=0) {
334 if (skipdot==2) up[cur]=$13 $12
335 else cur=$13 $12
336 skipdot=0
337 next
338 }
339 if (($2=="2e" && $3=="20") || ($2=="2e" && $3=="2e" && $4=="20")) {
340 if ($3=="2e") skipdot=2
341 else skipdot=1
342 next
343 }
344 if (gotname!=0) {
345 path=""
346 for (i=cur;i!="" && i!="0000";i=up[i]) path=dir[i] path
347 if (gotname==2) dir[$13 $12]=name
348 else print $1 " " $13 $12 " " path name
349 gotname=0
350 name=""
351 next
352 }
353 if (s!="") {
354 if (eos==0)
355 for (i=2;i<18;i+=2) {
356 if (i==12) i+=2
357 if ($i=="00") break
358 s=s substr($0,i+60,1)
359 }
360 name=s name
361 s=""
362 eos=0
363 next
364 }
365 if ($13=="0f") {
366 s=""
367 for (i=3;i<16;i+=2) {
368 if (i==13) i+=3
369 if ($i=="00") { eos=1; break }
370 s=s substr($0,i+60,1)
371 }
372 next
373 }
374 if ($13=="10") {
375 name=name "/"
376 gotname=2
377 next
378 }
379 if ($13=="20") {
380 gotname=1
381 next
382 }
383 }
384 ' | ( while read offset cluster file; do
385 cluster=$(($(first_block "$2/$file")-$basecluster))
386 set32 $(($efiblock*2048+0x$offset+10)) $cluster "$1" 16
387 set32 $(($efiblock*2048+0x$offset+4)) $(($cluster>>16)) "$1" 16
388 echo "$cluster $((($(stat -c %s "$2/$file")+2047)/2048)) $file"
389 done
391 # Update fat12 or fat16
392 get 57 "$2/boot/isolinux/efi.img"
393 dd if="$2/boot/isolinux/efi.img" bs=512 count=$fatsz skip=$resv 2> /dev/null | \
394 od -An -t u1 -w1 -v
395 ) | awk '
396 {
397 if (state==0) {
398 if ($2=="") {
399 if ($1==12849) fat=12
400 else if ($1==13873) fat=16
401 else fat=32
402 state++
403 }
404 else {
405 for (i=1;i<$2;i++) c[$1+i]=$1+i
406 c[$1+$2]=268435455
407 }
408 next
409 }
410 if (state==1) {
411 prev=$1
412 state++
413 next
414 }
415 if (state==2) {
416 if (fat==12) {
417 n=($1%16)*256+prev
418 if (n!=0) c[pos+1]=n
419 pos++
420 prev=int($1/16)
421 state++
422 next
423 }
424 n=$1*256+prev
425 if (fat==32) {
426 prev=n
427 state=13
428 next
429 }
430 }
431 else if (state==3) {
432 n=$1*16+prev
433 }
434 else if (state==13) {
435 prev=$1*65536+prev
436 state++
437 next
438 }
439 else n=$1*16777216+prev
440 if (n!=0) c[pos+1]=n
441 pos++
442 state=1
443 }
444 END {
445 for (i=1;i<=pos;i+=2) {
446 if (c[i]=="") c[i]=0
447 if (c[i+1]=="") c[i+1]=0
448 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
449 else if (fat==16) printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,c[i+1]%256,(c[i+1]/256)%256
450 else {
451 printf "0 %02X %02X %02X %02X |\n",c[i]%256,(c[i]/256)%256,(c[i]/65536)%256,(c[i]/16777216)%256
452 printf "0 %02X %02X %02X %02X |\n",c[i+1]%256,(c[i+1]/256)%256,(c[i+1]/65536)%256,(c[i+1]/16777216)%256
453 }
454 }
455 }' | hexdump -R | dd of="$1" seek=$((4*$efiblock+$fatsz+$resv)) \
456 conv=notrunc bs=512 > /dev/null 2>&1
457 dd if="$1" of="$1" conv=notrunc bs=512 skip=$((4*$efiblock+$fatsz+$resv)) \
458 count=$fatsz seek=$((4*$efiblock+$resv)) > /dev/null 2>&1
460 # Cleanup cache
461 umount $2
462 mount -o loop,ro $1 $2
463 }
466 # allocate efi.img stub to share EFI files in the EFI boot partition
468 alloc_uefi_part() {
469 local basedir=$(dirname "$1")/..
470 if [ -s $basedir/boot/isolinux/efi.img ]; then
471 chmod +x $basedir/boot/isolinux/efi.img
472 return
473 fi
474 local fclust=$({
475 [ -d $basedir/efi ] &&
476 find $basedir/efi -type f -exec stat -c "%s %n" {} \;
477 while [ -s "$1" ]; do
478 local efifile
479 case "$1" in
480 *taz) efifile=bootia32.efi ;;
481 *taz64) efifile=bootx64.efi ;;
482 esac
483 if [ ! -s $basedir/efi/boot/$efifile ] &&
484 [ $(get $((0x82)) "$1") = $((0x4550)) ]; then
485 mkdir -p $basedir/efi/boot 2> /dev/null
486 ln "$1" "$basedir/efi/boot/$efifile"
487 stat -c "%s %n" "$1"
488 for i in $basedir/boot/rootfs* ; do
489 ln "$i" $basedir/efi/boot/ &&
490 stat -c "%s %n" "$i"
491 done 2> /dev/null
492 [ -s $basedir/efi/boot/linux.cmdline ] ||
493 sed 's|/|\\|g' > $basedir/efi/boot/linux.cmdline <<EOT
494 rw root=0x100 autologin\
495 $( ( cd $basedir/efi/boot ; ls -r rootfs*gz ) | while read f ; do \
496 echo -n " initrd=/EFI/BOOT/$f";done)
497 EOT
498 fi
499 shift
500 done; } | sort | uniq | awk '{ n+=int(($1+2047)/2048) } END { print n+1 }')
501 [ ${fclust:-0} -eq 0 ] && return
502 local dclust=$( (cd $basedir; find efi -type d 2>/dev/null) | awk '
503 BEGIN {
504 FS="/"
505 }
506 NF > 1 {
507 d[NF $NF]+=2
508 d[NF-1 $(NF-1)]+=($NF+25)/13
509 }
510 END {
511 for (i in d)
512 n+=int((d[i]+63)/64)
513 print n
514 }')
515 local clusters=$(($fclust+$dclust))
516 if [ $clusters -lt 4068 ]; then
517 fsect=$(((($clusters+2)*3+1023)/1024))
518 ftype="31 32"
519 fhead="F8 FF FF"
520 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
521 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
522 rootsz=2
523 elif [ $clusters -lt 65525 ]; then
524 fsect=$((($clusters+2+255)/256))
525 ftype="31 36"
526 fhead="F8 FF FF FF"
527 rsect=$(( 1+ ((2*$fsect)-1)%4 ))
528 fsz="$(printf "%04X" $fsect | sed 's/\(..\)\(..\)/\2 \1/')"
529 rootsz=2
530 else
531 fsect=$((($clusters+2+127)/128))
532 ftype="33 32"
533 fhead="F8 FF FF 0F FF FF FF FF F8 FF FF 0F"
534 rsect=$(( 6+ ((2*$fsect)-6)%4 ))
535 fsz="$(printf "%08X" $fsect | sed 's/\(..\)\(..\)\(..\)\(..\)/\4 \3 \2 \1/')"
536 rootsz=1
537 fi
538 # reserved + fat*2 + root dir + dirs
539 count=$((($rsect + $fsect*2)/4 + $rootsz + $dclust ))
540 s=$((($count+$fclust)*4))
541 if [ $s -gt 65535 ]; then
542 size="00 00"
543 size32="$(printf "%02X %02X %02X %02X" $(($s%256)) \
544 $((($s>>8)%256)) $((($s>>16)%256)) $((($s>>24)%256)) )"
545 else
546 size="$(printf "%02X %02X" $(($s%256)) $((($s>>8)%256)) )"
547 size32="00 00 00 00"
548 fi
549 dd if=/dev/zero bs=512 of=$basedir/boot/isolinux/efi.img \
550 count=$s 2> /dev/null
552 # Create boot sector
553 doslabel="$(echo "SLITAZ BOOT " | od -v -N 11 -t x1 -w1 -An)"
554 if [ "$ftype" = "33 32" ]; then
555 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
556 conv=notrunc
557 0 eb 58 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
558 0 02 00 00 $size f8 00 00 20 00 40 00 00 00 00 00 |
559 0 $size32 $fsz 00 00 00 00 02 00 00 00 |
560 0 01 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |
561 0 80 00 29 00 00 00 00 $doslabel |
562 0 46 41 54 $ftype 20 20 20 cd 18 cd 19 eb fa |
563 EOT
564 while read ofs data; do
565 echo "0 ${data//:/ } |" | hexdump -R | dd conv=notrunc \
566 bs=1 seek=$ofs of=$basedir/boot/isolinux/efi.img
567 done <<EOT
568 510 55:aa:52:52:61:41
569 996 72:72:41:61:ff:ff:ff:ff:02
570 1022 55:aa
571 EOT
572 else
573 echo -en '\x55\xAA' | dd of=$basedir/boot/isolinux/efi.img \
574 seek=510 bs=1 conv=notrunc
575 hexdump -R <<EOT | dd of=$basedir/boot/isolinux/efi.img \
576 conv=notrunc
577 0 eb 3c 90 53 6c 69 54 61 7a 00 00 00 02 04 $rsect 00 |
578 0 02 40 00 $size f8 $fsz 20 00 40 00 00 00 00 00 |
579 0 $size32 80 00 29 00 00 00 00 $doslabel |
580 0 46 41 54 $ftype 20 20 20 cd 18 |
581 0 cd 19 eb fa |
582 EOT
583 fi 2> /dev/null
585 # Create fats
586 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
587 seek=$(($rsect)) bs=512 conv=notrunc 2> /dev/null
588 echo "0 $fhead |" | hexdump -R | dd of=$basedir/boot/isolinux/efi.img \
589 seek=$(($rsect+$fsect)) bs=512 conv=notrunc 2> /dev/null
591 # Add label
592 echo "0 $doslabel 08 |" | hexdump -R | \
593 dd of=$basedir/boot/isolinux/efi.img bs=512 conv=notrunc \
594 seek=$(($rsect+$fsect+$fsect)) 2> /dev/null
596 mkdir -p /tmp/mnt$$
597 mount -o loop $basedir/boot/isolinux/efi.img /tmp/mnt$$
598 ( cd $basedir; find efi -type d | cpio -o -H newc ) | \
599 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
600 sync
601 dd if=$basedir/boot/isolinux/efi.img of=/tmp/fat$$ \
602 skip=$rsect bs=512 count=$fsect 2> /dev/null
603 ( cd $basedir; find efi -type f | cpio -o -H newc ) | \
604 ( cd /tmp/mnt$$ ; cpio -idmu 2> /dev/null )
605 umount /tmp/mnt$$
606 cat /tmp/fat$$ /tmp/fat$$ | dd of=$basedir/boot/isolinux/efi.img \
607 seek=$rsect bs=512 conv=notrunc 2> /dev/null
608 rm /tmp/fat$$
609 rmdir /tmp/mnt$$
611 dd count=0 bs=2k of=$basedir/boot/isolinux/efi.img \
612 seek=$count 2> /dev/null
613 }
616 # isolinux.conf doesn't know the kernel version.
617 # We name the kernel image 'bzImage'.
618 # isolinux/syslinux first tries the '64' suffix with a 64bits cpu.
620 make_bzImage_hardlink() {
621 if [ -e ${1:-.}/vmlinuz*slitaz ]; then
622 rm -f ${1:-.}/bzImage 2>/dev/null
623 ln ${1:-.}/vmlinuz*slitaz ${1:-.}/bzImage
624 fi
625 if [ -e ${1:-.}/vmlinuz*slitaz64 ]; then
626 rm -f ${1:-.}/bzImage64 2> /dev/null
627 ln ${1:-.}/vmlinuz*slitaz64 ${1:-.}/bzImage64
628 fi
629 }
632 create_iso() {
633 cd $2
634 deduplicate
636 [ $(ls $2/boot/grub* 2> /dev/null | wc -l) -lt 2 ] && rm -rf $2/boot/grub*
637 make_bzImage_hardlink $2/boot
638 alloc_uefi_part $(ls -r $2/boot/vmlinuz*slitaz*)
640 cat > /tmp/cdsort$$ <<EOT
641 $PWD/boot/isolinux 100
642 $(ls -r $PWD/boot/rootfs* | awk 'BEGIN{n=149} { print $1 " " n-- }')
643 $(ls $PWD/boot/bzImage* | awk 'BEGIN{n=200} { print $1 " " n-- }')
644 $(find $PWD/efi -type f 2>/dev/null | sort -r | awk 'BEGIN{n=299} { print $1 " " n-- }')
645 $PWD/boot/isolinux/efi.img 300
646 $PWD/boot/isolinux/isolinux.bin 399
647 $PWD/boot/isolinux/boot.cat 400
648 EOT
650 action 'Computing md5...'
651 touch boot/isolinux/boot.cat
652 find * -type f ! -name md5sum ! -name 'vmlinuz-*' -exec md5sum {} \; | \
653 sort -k 2 > md5sum
654 status
656 cd - >/dev/null
657 title 'Generating ISO image'
659 _ 'Generating %s' "$1"
660 uefi="$(cd $2 ; ls boot/isolinux/efi.img 2> /dev/null)"
661 genisoimage -R -o $1 -hide-rr-moved -sort /tmp/cdsort$$ \
662 -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
663 -no-emul-boot -boot-load-size 4 -boot-info-table \
664 ${uefi:+-eltorito-alt-boot -efi-boot $uefi -no-emul-boot} \
665 -V "${VOLUM_NAME:-SliTaz}" -p "${PREPARED:-$(id -un)}" \
666 -volset "SliTaz $SLITAZ_VERSION" -input-charset utf-8 \
667 -A "tazlito $VERSION/$(genisoimage --version)" \
668 -copyright README -P "www.slitaz.org" -no-pad $2
669 rm -f /tmp/cdsort$$
670 dd if=/dev/zero bs=2k count=16 >> $1 2> /dev/null
672 mkdir /tmp/mnt$$
673 mount -o loop,ro $1 /tmp/mnt$$
674 fixup_uefi_part $1 /tmp/mnt$$
675 for i in boot/isolinux/isolinux.bin boot/isolinux/boot.cat \
676 ${uefi:+boot/isolinux/efi.img} ; do
677 sed -i "s|.* $i|$( cd /tmp/mnt$$ ; md5sum $i)|" $2/md5sum
678 done
679 dd if=$2/md5sum of=$1 conv=notrunc bs=2k \
680 seek=$(first_block /tmp/mnt$$/md5sum) 2> /dev/null
681 umount -d /tmp/mnt$$
682 rmdir /tmp/mnt$$
684 if [ -s '/etc/tazlito/info' ]; then
685 if [ $(stat -c %s /etc/tazlito/info) -lt $(( 31*1024 )) ]; then
686 action 'Storing ISO info...'
687 dd if=/etc/tazlito/info bs=1k seek=1 of=$1 conv=notrunc 2>/dev/null
688 status
689 fi
690 fi
692 if [ -x '/usr/bin/isohybrid' ]; then
693 action 'Creating hybrid ISO...'
694 isohybrid $1 $([ -n "$uefi" ] || echo -entry 2) 2>/dev/null
695 status
696 fi
698 if [ -x '/usr/bin/iso2exe' ]; then
699 echo 'Creating EXE header...'
700 /usr/bin/iso2exe $1 2>/dev/null
701 fi
702 }
705 # Generate a new ISO image using isolinux.
707 gen_livecd_isolinux() {
708 # Some packages may want to alter iso
709 genisohooks iso
710 [ ! -f "$ROOTCD/boot/isolinux/isolinux.bin" ] && die 'Unable to find isolinux binary.'
712 # Set date for boot msg.
713 if grep -q 'XXXXXXXX' "$ROOTCD/boot/isolinux/isolinux.cfg"; then
714 DATE=$(date +%Y%m%d)
715 action 'Setting build date to: %s...' "$DATE"
716 sed -i "s/XXXXXXXX/$DATE/" "$ROOTCD/boot/isolinux/isolinux.cfg"
717 status
718 fi
720 cd $DISTRO
721 create_iso $ISO_NAME.iso $ROOTCD
723 action 'Creating the ISO md5sum...'
724 md5sum $ISO_NAME.iso > $ISO_NAME.md5
725 status
727 separator
728 # Some packages may want to alter final iso
729 genisohooks final
730 }
733 lzma_history_bits() {
734 #
735 # This generates an ISO which boots with Qemu but gives
736 # rootfs errors in frugal or liveUSB mode.
737 #
738 # local n
739 # local sz
740 # n=20 # 1Mb
741 # sz=$(du -sk $1 | cut -f1)
742 # while [ $sz -gt 1024 -a $n -lt 28 ]; do
743 # n=$(( $n + 1 ))
744 # sz=$(( $sz / 2 ))
745 # done
746 # echo $n
747 echo ${LZMA_HISTORY_BITS:-24}
748 }
751 lzma_switches() {
752 local proc_num=$(grep -sc '^processor' /proc/cpuinfo)
753 echo "-d$(lzma_history_bits $1) -mt${proc_num:-1} -mc1000"
754 }
757 lzma_set_size() {
758 # Update size field for lzma'd file packed using -si switch
759 return # Need to fix kernel code?
761 local n i
762 n=$(unlzma < $1 | wc -c)
763 for i in $(seq 1 8); do
764 printf '\\\\x%02X' $(($n & 255))
765 n=$(($n >> 8))
766 done | xargs echo -en | dd of=$1 conv=notrunc bs=1 seek=5 2>/dev/null
767 }
770 align_to_32bits() {
771 local size=$(stat -c %s ${1:-/dev/null})
772 [ $((${size:-0} & 3)) -ne 0 ] &&
773 dd if=/dev/zero bs=1 count=$((4 - ($size & 3))) >> $1 2>/dev/null
774 }
777 dolz4() {
778 [ "$(which lz4)" ] || tazpkg get-install lz4
779 lz4 -9 > $1
780 }
783 dogzip() {
784 gzip -9 > $1
785 [ -x /usr/bin/advdef ] && advdef -qz4 $1
786 }
789 # Pack rootfs
791 pack_rootfs() {
792 ( cd $1; find . -print | cpio -o -H newc ) | \
793 case "$COMPRESSION" in
794 none)
795 _ 'Creating %s without compression...' 'initramfs'
796 cat > $2
797 ;;
798 lz4)
799 _ 'Creating %s with lz4 compression...' 'initramfs'
800 dolz4 $2
801 ;;
802 gzip)
803 _ 'Creating %s with gzip compression...' 'initramfs'
804 dogzip $2
805 ;;
806 *)
807 _ 'Creating %s with lzma compression...' 'initramfs'
808 lzma e -si -so $(lzma_switches $1) > $2
809 lzma_set_size $2
810 ;;
811 esac
812 align_to_32bits $2
813 echo 1 > /tmp/rootfs
814 }
817 # Compression functions for writeiso.
819 write_initramfs() {
820 case "$COMPRESSION" in
821 lzma)
822 _n 'Creating %s with lzma compression...' "$INITRAMFS"
823 cpio -o -H newc | lzma e -si -so $(lzma_switches) > "/$INITRAMFS"
824 align='y'
825 lzma_set_size "/$INITRAMFS"
826 ;;
827 gzip)
828 _ 'Creating %s with gzip compression...' "$INITRAMFS"
829 cpio -o -H newc | dogzip "/$INITRAMFS"
830 ;;
831 lz4)
832 _ 'Creating %s with lz4 compression...' "$INITRAMFS"
833 cpio -o -H newc | dolz4 "/$INITRAMFS"
834 ;;
835 *)
836 # align='y'
837 _ 'Creating %s without compression...' "$INITRAMFS"
838 cpio -o -H newc > "/$INITRAMFS"
839 ;;
840 esac < /tmp/list
841 [ "$align" = 'y' -a -z "$noalign" ] && align_to_32bits "/$INITRAMFS"
842 echo 1 > /tmp/rootfs
843 }
846 # Deduplicate files (MUST be on the same filesystem).
848 deduplicate() {
849 find "${@:-.}" -xdev -type f -size +0c -exec stat -c '%s-%a-%u-%g %i %h %n' {} \; | sort | \
850 (
851 save=0; hardlinks=0; old_attr=""; old_inode=""; old_link=""; old_file=""
852 while read attr inode link file; do
853 [ -L "$file" ] && continue
854 if [ "$attr" = "$old_attr" -a "$inode" != "$old_inode" ]; then
855 if cmp "$file" "$old_file" >/dev/null 2>&1 ; then
856 rm -f "$file"
857 if ln "$old_file" "$file" 2>/dev/null; then
858 inode="$old_inode"
859 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1)) &&
860 save="$(($save+(${attr%%-*}+512)/1024))"
861 else
862 cp -a "$old_file" "$file"
863 fi
864 fi
865 fi
866 old_attr="$attr" ; old_inode="$inode" ; old_file="$file"
867 done
868 _ '%s Kbytes saved in %s duplicate files.' "$save" "$hardlinks"
869 )
871 find "$@" -xdev -type l -exec stat -c '%s-%u-%g %i %h %n' {} \; | \
872 while read attr inode link file; do
873 echo "$attr-$(readlink "$file" | uuencode -m - | \
874 sed '1d;:b;{N;s/\n//;bb;}') $inode $link $file"
875 done | sort | \
876 (
877 old_attr=""; hardlinks=0;
878 while read attr inode link file; do
879 if [ "$attr" = "$old_attr" ]; then
880 if [ "$inode" != "$old_inode" ]; then
881 rm -f "$file"
882 if ln "$old_file" "$file" 2>/dev/null; then
883 [ "$link" -eq 1 ] && hardlinks=$(($hardlinks+1))
884 else
885 cp -a "$old_file" "$file"
886 fi
887 fi
888 else
889 old_file="$file"
890 old_attr="$attr"
891 old_inode="$inode"
892 fi
893 done
894 _ '%s duplicate symlinks.' "$hardlinks"
895 )
896 }
899 # Generate a new initramfs from the root filesystem.
901 gen_initramfs() {
902 # Just in case CTRL+c
903 rm -f $DISTRO/gen
905 # Some packages may want to alter rootfs
906 genisohooks rootfs
907 cd $1
909 # Normalize file time
910 find $1 -newer $1 -exec touch -hr $1 {} \;
912 # Link duplicate files
913 deduplicate
915 # Use lzma if installed. Display rootfs size in realtime.
916 rm -f /tmp/rootfs 2>/dev/null
917 pack_rootfs . $DISTRO/$(basename $1).gz &
918 sleep 2
919 echo -en "\nFilesystem size:"
920 while [ ! -f /tmp/rootfs ]; do
921 sleep 1
922 echo -en "\\033[18G$(du -sh $DISTRO/$(basename $1).gz | awk '{print $1}') "
923 done
924 echo -e "\n"
925 rm -f /tmp/rootfs
926 cd $DISTRO
927 mv $(basename $1).gz $ROOTCD/boot
928 }
931 distro_sizes() {
932 if [ -n "$start_time" ]; then
933 time=$(($(date +%s) - $start_time))
934 sec=$time
935 div=$(( ($time + 30) / 60))
936 [ "$div" -ne 0 ] && min="~ ${div}m"
937 _ 'Build time : %ss %s' "$sec" "$min"
938 fi
939 cat <<EOT
940 Build date : $(date +%Y%m%d)
941 Packages : $(ls -1 $ROOTFS*$INSTALLED/*/receipt | wc -l)
942 Rootfs size : $(du -csh $ROOTFS*/ | awk 'END { print $1 }')
943 Initramfs size : $(du -csh $ROOTCD/boot/rootfs*.gz | awk 'END { print $1 }')
944 ISO image size : $(du -sh $ISO_NAME.iso | awk '{ print $1 }')
945 EOT
946 footer "Image is ready: $ISO_NAME.iso"
947 }
950 # Print ISO and rootfs size.
952 distro_stats() {
953 title 'Distro statistics: %s' "$DISTRO"
954 distro_sizes
955 }
958 # Create an empty configuration file.
960 empty_config_file() {
961 cat >> tazlito.conf <<"EOF"
962 # tazlito.conf: Tazlito (SliTaz Live Tool) configuration file.
963 #
965 # Name of the ISO image to generate.
966 ISO_NAME=""
968 # ISO image volume name.
969 VOLUM_NAME="SliTaz"
971 # Name of the preparer.
972 PREPARED="$USER"
974 # Path to the packages repository and the packages.list.
975 PACKAGES_REPOSITORY=""
977 # Path to the distro tree to gen-distro from a list of packages.
978 DISTRO=""
980 # Path to the directory containing additional files
981 # to copy into the rootfs and rootcd of the LiveCD.
982 ADDFILES="$DISTRO/addfiles"
984 # Default answer for binary question (Y or N)
985 DEFAULT_ANSWER="ASK"
987 # Compression utility (lzma, gzip or none)
988 COMPRESSION="lzma"
989 EOF
990 }
993 # Extract rootfs.gz somewhere
995 extract_rootfs() {
996 # Detect compression format: *.lzma.cpio, *.gzip.cpio, or *.cpio
997 # First part (lzcat or zcat) may not fail, but cpio will fail on incorrect format
998 (cd "$2"; lzcat "$1" | cpio -idm --quiet 2>/dev/null) && return
999 (cd "$2"; zcat "$1" | cpio -idm --quiet 2>/dev/null) && return
1000 (cd "$2"; cat "$1" | cpio -idm --quiet 2>/dev/null)
1004 # Extract flavor file to temp directory
1006 extract_flavor() {
1007 # Input: $1 - flavor name to extract;
1008 # $2 = absent/empty: just extract 'outer layer'
1009 # $2 = 'full': also extract 'inner' rootcd and rootfs archives, make files rename
1010 # $2 = 'info': as 'full' and also make 'info' file to put into ISO
1011 # Output: temp dir path where flavor was extracted
1012 local f="$1.flavor" from to infos="$1.desc"
1013 [ -f "$f" ] || die "File '$f' not found"
1014 local dir="$(mktemp -d)"
1015 zcat "$f" | (cd $dir; cpio -i --quiet >/dev/null)
1017 if [ -n "$2" ]; then
1018 cd $dir
1020 [ -s "$1.receipt" ] && infos="$infos\n$1.receipt"
1022 for i in rootcd rootfs; do
1023 [ -f "$1.$i" ] || continue
1024 mkdir "$i"
1025 zcat "$1.$i" | (cd "$i"; cpio -idm --quiet 2>/dev/null)
1026 zcat "$1.$i" | cpio -tv 2>/dev/null > "$1.list$i"; infos="$infos\n$1.list$i"
1027 rm "$1.$i"
1028 done
1029 touch -t 197001010100.00 $1.*
1030 # Info to be stored inside ISO
1031 [ "$2" = info ] && echo -e $infos | cpio -o -H newc | dogzip info
1032 rm $1.list*
1034 # Renames
1035 while read from to; do
1036 [ -f "$from" ] || continue
1037 mv "$from" "$to"
1038 done <<EOT
1039 $1.nonfree non-free.list
1040 $1.pkglist packages.list
1041 $1-distro.sh distro.sh
1042 $1.receipt receipt
1043 $1.mirrors mirrors
1044 $1.desc description
1045 EOT
1046 fi
1048 echo $dir
1052 # Pack flavor file from temp directory
1054 pack_flavor() {
1055 (cd "$1"; ls | grep -v err | cpio -o -H newc) | dogzip "$2.flavor"
1059 # Remove duplicate files
1061 files_match() {
1062 if [ -d "$1" ]; then
1063 return 1
1065 elif [ -L "$1" ] && [ -L "$2" ]; then
1066 [ "$(readlink "$1")" = "$(readlink "$2")" ] && return 0
1068 elif [ -f "$1" ] && [ -f "$2" ]; then
1069 cmp -s "$1" "$2" && return 0
1071 [ "$(basename "$3")" = 'volatile.cpio.gz' ] &&
1072 [ "$(dirname $(dirname "$3"))" = ".$INSTALLED" ] &&
1073 return 0
1075 elif [ "$(ls -l "$1"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$1")" = \
1076 "$(ls -l "$2"|cut -c1-10)$(stat -c '%a:%u:%g:%t:%T' "$2")" ]; then
1077 return 0
1079 fi 2> /dev/null
1080 return 1
1083 remove_with_path() {
1084 dir="$(dirname $1)"
1085 rm -f "$1"
1086 while rmdir "$dir" 2> /dev/null; do
1087 dir="$(dirname $dir)"
1088 done
1091 mergefs() {
1092 # Note, many packages have files with spaces in the name
1093 IFS=$'\n'
1095 local size1=$(du -hs "$1" | awk '{ print $1 }')
1096 local size2=$(du -hs "$2" | awk '{ print $1 }')
1097 action 'Merge %s (%s) into %s (%s)' "$(basename "$1")" "$size1" "$(basename "$2")" "$size2"
1099 # merge symlinks files and devices
1100 ( cd "$1"; find ) | \
1101 while read file; do
1102 files_match "$1/$file" "$2/$file" "$file" &&
1103 remove_with_path "$2/$file"
1104 [ -d "$1/$file" ] && [ -d "$2/$file" ] && rmdir "$2/$file" 2>/dev/null
1105 done
1107 unset IFS
1108 status
1112 cleanup_merge() {
1113 rm -rf $TMP_DIR
1114 exit 1
1118 # Update isolinux config files for multiple rootfs
1120 update_bootconfig() {
1121 local files
1122 action 'Updating boot config files...'
1123 files="$(grep -l 'include common' $1/*.cfg)"
1124 for file in $files; do
1125 awk -v n=$(echo $2 | awk '{ print NF/2 }') '{
1126 if (/label/) label=$0;
1127 else if (/kernel/) kernel=$0;
1128 else if (/append/) {
1129 i=index($0,"rootfs.gz");
1130 append=substr($0,i+9);
1132 else if (/include/) {
1133 for (i = 1; i <= n; i++) {
1134 print label i
1135 print kernel;
1136 initrd="initrd=/boot/rootfs" n ".gz"
1137 for (j = n - 1; j >= i; j--) {
1138 initrd=initrd ",/boot/rootfs" j ".gz";
1140 printf "\tappend %s%s\n",initrd,append;
1141 print "";
1143 print;
1145 else print;
1146 }' < $file > $file.$$
1147 mv -f $file.$$ $file
1148 done
1149 sel="$(echo $2 | awk '{
1150 for (i=1; i<=NF; i++)
1151 if (i % 2 == 0) printf " slitaz%d", i/2
1152 else printf " %s", $i
1153 }')"
1155 [ -s $1/common.cfg ] && cat >> $1/common.cfg <<EOT
1157 label slitaz
1158 kernel /boot/isolinux/ifmem.c32
1159 append$sel noram
1161 label noram
1162 config noram.cfg
1164 EOT
1166 # Update vesamenu
1167 if [ -s "$1/isolinux.cfg" ]; then
1168 files="$files $1/isolinux.cfg"
1169 awk -v n=$(echo $2 | awk '{ print NF/2 }') -v "sel=$sel" '
1170 BEGIN {
1171 kernel = " COM32 c32box.c32"
1174 if (/ROWS/) print "MENU ROWS " n+$3;
1175 else if (/TIMEOUTROW/) print "MENU TIMEOUTROW " n+$3;
1176 else if (/TABMSGROW/) print "MENU TABMSGROW " n+$3;
1177 else if (/CMDLINEROW/) print "MENU CMDLINEROW " n+$3;
1178 else if (/VSHIFT/) {
1179 x = $3-n;
1180 if (x < 0) x = 0;
1181 print "MENU VSHIFT " x;
1183 else if (/rootfs.gz/) {
1184 linux = "";
1185 if (/bzImage/) linux = "linux /boot/bzImage ";
1186 i = index($0, "rootfs.gz");
1187 append = substr($0, i+9);
1188 printf "\tkernel /boot/isolinux/ifmem.c32\n";
1189 printf "\tappend%s noram\n", sel;
1190 printf "\nlabel noram\n\tMENU HIDE\n\tconfig noram.cfg\n\n";
1191 for (i = 1; i <= n; i++) {
1192 print "LABEL slitaz" i
1193 printf "\tMENU LABEL SliTaz slitaz%d Live\n", i;
1194 printf "%s\n", kernel;
1195 initrd = "initrd=/boot/rootfs" n ".gz"
1196 for (j = n - 1; j >= i; j--) {
1197 initrd = initrd ",/boot/rootfs" j ".gz";
1199 printf "\tappend %s%s%s\n\n", linux, initrd, append;
1202 else if (/bzImage/) kernel = $0;
1203 else print;
1204 }' < $1/isolinux.cfg > $1/isolinux.cfg.$$
1205 mv $1/isolinux.cfg.$$ $1/isolinux.cfg
1206 fi
1208 [ -s $1/c32box.c32 ] && sed -i -e '/kernel.*ifmem/d' \
1209 -e 's/append \([0-9]\)/append ifmem \1/' $1/isolinux.cfg
1210 cat > $1/noram.cfg <<EOT
1211 implicit 0
1212 prompt 1
1213 timeout 80
1214 $(grep '^F[0-9]' $1/isolinux.cfg)
1216 $([ -s $1/isolinux.msg ] && echo display isolinux.msg)
1217 say Not enough RAM to boot slitaz. Trying hacker mode...
1218 default hacker
1219 label hacker
1220 KERNEL /boot/bzImage
1221 append rw root=/dev/null vga=normal
1223 label reboot
1224 EOT
1226 if [ -s $1/c32box.c32 ]; then
1227 cat >> $1/noram.cfg <<EOT
1228 COM32 c32box.c32
1229 append reboot
1231 label poweroff
1232 COM32 c32box.c32
1233 append poweroff
1235 EOT
1236 else
1237 echo " com32 reboot.c32" >> $1/noram.cfg
1238 fi
1240 # Restore real label names
1241 [ -s $1/common.cfg ] && files="$1/common.cfg $files"
1242 echo $2 | awk '{ for (i=NF; i>1; i-=2) printf "%d/%s\n",i/2,$i }' | \
1243 while read pat; do
1244 sed -i "s/slitaz$pat/" $files
1245 done
1246 status
1250 # Uncompress rootfs or module to stdout
1252 uncompress() {
1253 zcat $1 2> /dev/null || xzcat $1 2> /dev/null ||
1254 { [ $(od -N 1 -An $1) -eq 135 ] && unlzma < $1; } || cat $1
1258 # Install a missing package
1260 install_package() {
1261 if [ -z "$2" ]; then
1262 answer=$(yesorno "$(_ 'Install package %s?' "$1")" 'n')
1263 else
1264 answer=$(yesorno "$(_n 'Install package %s for Kernel %s? ' "$1" "$2")" 'n')
1265 fi
1266 case "$answer" in
1267 y)
1268 # We don't want package on host cache.
1269 action 'Getting and installing package: %s' "$1"
1270 yes y | tazpkg get-install $1 --quiet 2>&1 >> $log || exit 1
1271 status ;;
1272 *)
1273 return 1 ;;
1274 esac
1278 # Check iso for loram transformation
1280 check_iso_for_loram() {
1281 [ -s "$TMP_DIR/iso/boot/rootfs.gz" ] ||
1282 [ -s "$TMP_DIR/iso/boot/rootfs1.gz" ]
1286 # Remove duplicated files in $1/efi/boot from $1/boot
1288 cleanup_efi_boot() {
1289 [ -s $1/boot/isolinux/efi.img ] &&
1290 [ ! -x $1/boot/isolinux/efi.img ] &&
1291 rm -f $1/boot/isolinux/efi.img
1292 for i in $1/efi/boot/* ; do
1293 [ -f $i ] || continue
1294 case "$i" in
1295 */rootfs*) cmp $i ${i/\/efi\//\/} || continue ;;
1296 */bootia32.efi) cmp $i $1/boot/bzImage || continue
1297 rm $1/efi/boot/linux.cmdline ;;
1298 */bootx64.efi) cmp $i $1/boot/bzImage64 || continue
1299 rm $1/efi/boot/linux.cmdline* ;;
1300 esac
1301 rm -f $i
1302 rmdir $1/efi/boot && rmdir $1/efi
1303 done 2> /dev/null
1307 # Build initial rootfs for loram ISO ram/cdrom/http
1309 build_initfs() {
1310 urliso="mirror.switch.ch/ftp/mirror/slitaz \
1311 download.tuxfamily.org/slitaz mirror1.slitaz.org mirror2.slitaz.org \
1312 mirror3.slitaz.org mirror.slitaz.org"
1313 version=$(ls $TMP_DIR/iso/boot/vmlinuz-* | sed 's/.*vmlinuz-//')
1314 [ -z "$version" ] && die "Can't find the kernel version." \
1315 'No file /boot/vmlinuz-<version> in ISO image. Abort.'
1317 [ -s /usr/share/boot/busybox-static ] || install_package busybox-static
1318 need_lib=false
1319 for i in bin dev run mnt proc tmp sys lib/modules/64; do
1320 mkdir -p $TMP_DIR/initfs/$i
1321 done
1322 ln -s bin $TMP_DIR/initfs/sbin
1323 ln -s . $TMP_DIR/initfs/usr
1324 for aufs in aufs overlayfs; do
1325 for v in $version ; do
1326 [ -f /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z ] && continue
1327 install_package ${v/*taz/linux}-$aufs $v && continue
1328 done
1329 install_package $aufs $version && break
1330 done || return 1
1331 [ -s /init ] || install_package slitaz-boot-scripts
1332 cp /init $TMP_DIR/initfs/
1333 for v in $version ; do
1334 cp /lib/modules/$v/kernel/fs/$aufs/$aufs.ko.?z \
1335 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1336 done
1337 if [ "$1" = 'cdrom' ]; then
1338 sed -i '/mod squashfs/d' $TMP_DIR/initfs/init
1339 else
1340 [ ! -f /usr/sbin/mksquashfs ] && ! install_package squashfs && return 1
1341 for v in $version ; do
1342 while [ ! -f /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z ]; do
1343 install_package linux-squashfs $v || return 1
1344 done
1345 done
1346 for v in $version ; do
1347 cp /lib/modules/$v/kernel/fs/squashfs/squashfs.ko.?z \
1348 $TMP_DIR/initfs/lib/modules/${v/*taz/}
1349 done
1350 #ls /sbin/unsquashfs /usr/lib/liblzma.so* $INSTALLED/squashfs/* | \
1351 #cpio -o -H newc > $TMP_DIR/initfs/extractfs.cpio
1352 fi
1353 if [ "$1" = 'http' ]; then
1354 mkdir $TMP_DIR/initfs/etc $TMP_DIR/fs
1355 ln -s /proc/mounts $TMP_DIR/initfs/etc/mtab
1356 cp /usr/share/udhcpc/default.script $TMP_DIR/initfs/lib/udhcpc
1357 sed -i 's|/sbin/||;s/^logger/#&/' $TMP_DIR/initfs/lib/udhcpc
1358 cp -a /dev/fuse $TMP_DIR/initfs/dev
1359 if ! $need_lib && [ -x /usr/share/boot/fusermount-static ]; then
1360 cp /usr/share/boot/fusermount-static $TMP_DIR/initfs/bin/fusermount
1361 else
1362 need_lib=true
1363 fi
1364 if ! $need_lib && [ -x /usr/share/boot/httpfs-static ]; then
1365 cp /usr/share/boot/httpfs-static $TMP_DIR/initfs/bin/httpfs
1366 else
1367 [ ! -f /usr/bin/httpfs ] && ! install_package httpfs-fuse && return 1
1368 cp /usr/bin/httpfs $TMP_DIR/initfs/bin
1369 cp /usr/bin/fusermount $TMP_DIR/initfs/bin
1370 cp -a /lib/librt* $TMP_DIR/initfs/lib
1371 cp -a /lib/libdl* $TMP_DIR/initfs/lib
1372 cp -a /lib/libpthread* $TMP_DIR/initfs/lib
1373 cp -a /usr/lib/libfuse* $TMP_DIR/initfs/lib
1374 cp -a /lib/libresolv* $TMP_DIR/initfs/lib
1375 cp -a /lib/libnss_dns* $TMP_DIR/initfs/lib
1376 need_lib=true
1377 fi
1378 cd $TMP_DIR/fs
1379 echo 'Getting slitaz-release & ethernet modules...'
1380 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
1381 uncompress $i | cpio -idmu etc/slitaz-release lib/modules rootfs*
1382 [ -s rootfs* ] || continue
1383 unsquashfs -f -d . rootfs* rootfs* etc/slitaz-release lib/modules &&
1384 rm -f rootfs*
1385 done 2>&1 > /dev/null
1386 cd - > /dev/null
1387 cp $TMP_DIR/fs/etc/slitaz-release $TMP_DIR/initfs/etc/
1388 for v in $version ; do
1389 find $TMP_DIR/fs/lib/modules/$v/kernel/drivers/net/ethernet \
1390 -type f -name '*.ko*' | while read mod; do
1391 f=$TMP_DIR/initfs/lib/modules/${v/*taz/}/$(basename $mod | sed s/..z$//)
1392 uncompress $mod > $f
1393 grep -q alias=pci: $f || rm -f $f
1394 done
1395 for i in $TMP_DIR/initfs/lib/modules/${v/*taz/}/*.ko ; do
1396 f=$(basename $i)..z
1397 grep -q $f:$ $TMP_DIR/fs/lib/modules/$v/modules.dep && continue
1398 deps="$(grep $f: $TMP_DIR/fs/lib/modules/$v/modules.dep | sed 's/.*: //')"
1399 echo "$deps" | sed 's|kernel/[^ ]*/||g;s/.ko..z//g' > ${i/.ko/}.dep
1400 for j in $deps; do
1401 mod=$(ls $TMP_DIR/fs/lib/modules/$v/$j)
1402 uncompress $mod > $(echo $j | sed s/..z$//)
1403 done
1404 done
1405 done
1406 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"
1407 _n 'List of URLs to insert: '
1408 read -t 30 urliso2
1409 urliso="$urliso2 $urliso"
1410 fi
1411 if ! $need_lib && [ -x /usr/share/boot/busybox-static ]; then
1412 cp /usr/share/boot/busybox-static $TMP_DIR/initfs/bin/busybox
1413 sed -i 's/LD_T.*ot/echo/;s/".*ld-.*) /"/' $TMP_DIR/initfs/init
1414 else
1415 cp /bin/busybox $TMP_DIR/initfs/bin
1416 if ! cmp /bin/busybox /sbin/insmod > /dev/null ; then
1417 cp /sbin/insmod $TMP_DIR/initfs/bin
1418 cp -a /lib/libkmod.so.* $TMP_DIR/initfs/lib
1419 cp -a /usr/lib/liblzma.so.* $TMP_DIR/initfs/lib
1420 cp -a /usr/lib/libz.so.* $TMP_DIR/initfs/lib
1421 fi
1422 need_lib=true
1423 fi
1424 for i in $($TMP_DIR/initfs/bin/busybox | awk \
1425 '{ if (s) printf "%s",$0 } /Currently/ { s=1 }' | sed 's/,//g'); do
1426 ln $TMP_DIR/initfs/bin/busybox $TMP_DIR/initfs/bin/$i
1427 done
1428 # bootfloppybox will need floppy.ko.?z, /dev/fd0, /dev/tty0
1429 for v in $version ; do
1430 cp /lib/modules/$v/kernel/drivers/block/floppy.ko.?z \
1431 $TMP_DIR/initfs/lib/modules/${v/*taz/} 2>/dev/null
1432 done
1433 for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/zero \
1434 /dev/kmem /dev/mem /dev/random /dev/urandom; do
1435 cp -a $i $TMP_DIR/initfs/dev
1436 done
1437 grep -q '/sys/block/./dev' $TMP_DIR/initfs/init ||
1438 for i in /dev/fd0 /dev/[hs]d[a-f]* /dev/loop* ; do
1439 cp -a $i $TMP_DIR/initfs/dev
1440 done 2>/dev/null
1441 $need_lib && for i in /lib/ld-* /lib/lib[cm][-\.]* ; do
1442 cp -a $i $TMP_DIR/initfs/lib
1443 done
1444 [ "$1" = 'http' ] && cat > $TMP_DIR/initfs/init <<EOTEOT
1445 #!/bin/sh
1447 getarg() {
1448 grep -q " \$1=" /proc/cmdline || return 1
1449 eval \$2=\$(sed "s/.* \$1=\\\\([^ ]*\\\\).*/\\\\1/" < /proc/cmdline)
1450 return 0
1453 copy_rootfs() {
1454 total=\$(grep MemTotal /proc/meminfo | sed 's/[^0-9]//g')
1455 need=\$(du -c \${path}rootfs* | tail -n 1 | cut -f1)
1456 [ \$(( \$total / \$need )) -gt 1 ] || return 1
1457 if ! grep -q " keep-loram" /proc/cmdline && cp \${path}rootfs* /mnt; then
1458 path=/mnt/
1459 return 0
1460 else
1461 rm -f /mnt/rootfs*
1462 return 1
1463 fi
1466 echo "Switching / to tmpfs..."
1467 mount -t proc proc /proc
1468 size="\$(grep rootfssize= < /proc/cmdline | \\
1469 sed 's/.*rootfssize=\\([0-9]*[kmg%]\\).*/-o size=\\1/')"
1470 [ -n "\$size" ] || size="-o size=90%"
1472 mount -t sysfs sysfs /sys
1473 for i in /lib/modules/*/*.ko /lib/modules/*.ko ; do
1474 [ -s \$i ] && continue
1475 echo -en "Probe \$i \\r"
1476 for j in \$(grep alias=pci: \$i | sed 's/alias//;s/\*/.*/g'); do
1477 grep -q "\$j" /sys/bus/pci/devices/*/uevent || continue
1478 for k in \$(cat \${i/ko/dep} 2> /dev/null); do
1479 insmod /lib/modules/\$k.ko 2> /dev/null
1480 done
1481 echo "Loading \$i"
1482 insmod \$i 2> /dev/null
1483 break
1484 done
1485 done
1486 umount /sys
1487 while read var default; do
1488 eval \$var=\$default
1489 getarg \$var \$var
1490 done <<EOT
1491 eth eth0
1492 dns 208.67.222.222,208.67.220.220
1493 netmask 255.255.255.0
1494 gw
1495 ip
1496 EOT
1497 grep -q \$eth /proc/net/dev || sh
1498 if [ -n "\$ip" ]; then
1499 ifconfig \$eth \$ip netmask \$netmask up
1500 route add default gateway \$gw
1501 for i in \$(echo \$dns | sed 's/,/ /g'); do
1502 echo "nameserver \$i" >> /etc/resolv.conf
1503 done
1504 else
1505 udhcpc -f -q -s /lib/udhcpc -i \$eth
1506 fi
1507 for i in $urliso ; do
1508 [ -n "\$URLISO" ] && URLISO="\$URLISO,"
1509 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"
1510 URLISO="\$URLISO,http://\$i/iso/rolling/slitaz-rolling-loram-cdrom.iso,http://\$i/iso/rolling/slitaz-rolling-loram.iso"
1511 done
1512 getarg urliso URLISO
1513 DIR=fs
1514 if getarg loram DIR; then
1515 DEVICE=\${DIR%,*}
1516 DIR=/\${DIR#*,}
1517 fi
1518 mount -t tmpfs \$size tmpfs /mnt
1519 path2=/mnt/.httpfs/
1520 path=/mnt/.cdrom/
1521 mkdir -p /mnt/.rw /mnt/.wd \$path \$path2
1522 while [ ! -d \$path/boot ]; do
1523 for i in \$(echo \$URLISO | sed 's/,/ /g'); do
1524 httpfs \$i \$path2 && echo \$i && break
1525 done
1526 mount -o loop,ro -t iso9660 \$path2/*.iso \$path || sh
1527 done
1529 memfree=\$(grep MemFree /proc/meminfo | sed 's/[^0-9]//g')
1530 umount /proc
1531 branch=:/mnt/.cdrom/\$DIR
1532 if [ ! -d /mnt/.cdrom/\$DIR/etc ]; then
1533 branch=
1534 lp=1
1535 for i in /lib/modules/*/squashfs.ko /lib/modules/squashfs.ko ; do
1536 [ -s \$i ] && insmod \$i
1537 done 2> /dev/null
1538 for i in \${path}boot/rootfs?.* ; do
1539 fs=\${i#*root}
1540 branch=\$branch:/mnt/.\$fs
1541 mkdir -p /mnt/.rw/mnt/.\$fs /mnt/.\$fs /mnt/.rw/mnt/.cdrom
1542 losetup -o 124 /dev/loop\$lp \$i
1543 mount -o loop,ro -t squashfs /dev/loop\$lp /mnt/.\$fs
1544 lp=\$((\$lp+1))
1545 done
1546 fi
1547 mkdir -p /mnt/.rw/mnt/.httpfs
1548 while read type opt; do
1549 for i in /lib/modules/*/\$type.ko /lib/modules/\$type.ko ; do
1550 [ -s \$i ] && insmod \$i &&
1551 mount -t \$type -o \$opt none /mnt && break 2
1552 done
1553 done <<EOT
1554 aufs br=/mnt/.rw\$branch
1555 overlayfs workdir=/mnt/.wd\${branch/:/,lowerdir=},upperdir=/mnt/.rw
1556 EOT
1557 rm -rf /lib/modules
1558 [ -x /bin/httpfs ] && sed -i 's/DHCP="yes"/DHCP="no"/' /mnt/etc/network.conf
1559 [ \$memfree -lt 30000 ] && sed -i 's/ slim//' /mnt/etc/rcS.conf
1560 [ -x /mnt/sbin/init ] && exec /bin/switch_root mnt /sbin/init || sh
1561 EOTEOT
1562 chmod +x $TMP_DIR/initfs/init
1563 for i in $TMP_DIR/initfs/lib/modules/*z $TMP_DIR/initfs/lib/modules/*/*z ; do
1564 [ -s $i ] || continue
1565 unxz $i || gunzip $i || lzma d $i ${i%.gz}
1566 rm -f $i
1567 done 2>/dev/null
1568 (cd $TMP_DIR/initfs; find | busybox cpio -o -H newc 2>/dev/null) | \
1569 lzma e $TMP_DIR/initfs.gz -si
1570 lzma_set_size $TMP_DIR/initfs.gz
1571 rm -rf $TMP_DIR/initfs
1572 align_to_32bits $TMP_DIR/initfs.gz
1573 return 0
1577 # Move each initramfs to squashfs
1579 build_loram_rootfs() {
1580 rootfs_sizes=""
1581 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*); do
1582 mkdir -p $TMP_DIR/fs
1583 cd $TMP_DIR/fs
1584 uncompress $i | cpio -idm
1585 deduplicate
1586 cd - > /dev/null
1587 rootfs=$TMP_DIR/$(basename $i 64)
1588 [ $rootfs = $TMP_DIR/rootfs.gz ] && rootfs=$TMP_DIR/rootfs0.gz
1589 /usr/sbin/mksquashfs $TMP_DIR/fs $rootfs -comp ${1:-xz -Xbcj x86}
1590 cd $TMP_DIR
1591 rootfs_sizes="$rootfs_sizes $(( $(du -s $TMP_DIR/fs | cut -f1) - $(du -s $rootfs | cut -f1) ))"
1592 ( cd $(dirname $rootfs); echo $(basename $rootfs) | cpio -o -H newc ) > $rootfs.cpio
1593 [ $(ls -a fs | wc -l) -le 2 ] && cpio -o -H newc > $rootfs.cpio < /dev/null
1594 case "$i" in *64) rootfs=${rootfs}64 ;; esac
1595 rm -f $rootfs
1596 mv ${rootfs%64}.cpio $rootfs
1597 cd - > /dev/null
1598 rm -rf $TMP_DIR/fs
1599 done
1603 # Move meta boot configuration files to basic configuration files
1604 # because meta loram flavor is useless when rootfs is not loaded in RAM
1606 unmeta_boot() {
1607 local root=${1:-$TMP_DIR/loramiso}
1608 if [ -f $root/boot/isolinux/noram.cfg ]; then
1609 # We keep enough information to do unloram...
1610 [ -s $root/boot/isolinux/common.cfg ] &&
1611 sed -i 's/label slitaz/label orgslitaz/' \
1612 $root/boot/isolinux/common.cfg
1613 set -- $(grep 'append ifmem [0-9]' $root/boot/isolinux/isolinux.cfg)
1614 shift
1615 sed -i '/ifmem/{NNNNNNNNd};/^LABEL/{N;/LABEL SliTaz [^L]/{NNNd}}' \
1616 $root/boot/isolinux/isolinux.cfg
1617 [ -n "$3" ] || set -- $(grep 'append [0-9]' $root/boot/isolinux/common.cfg)
1618 sed -i "s/label $3\$/label slitaz/;s|=\(.*rootfs\)\(.*\)\.gz |=\1.gz |" \
1619 $root/boot/isolinux/*.cfg
1620 fi
1624 # Move rootfs to squashfs filesystem(s) to the cdrom writeable with aufs/overlayfs.
1625 # These squashfs may be loaded in RAM at boot time.
1626 # Rootfs are also copied to CD-ROM for tiny ramsize systems.
1627 # Meta flavors are converted to normal flavors.
1629 build_loram_cdrom() {
1630 build_initfs cdrom || return 1
1631 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1632 cleanup_efi_boot $TMP_DIR/loramiso
1633 mkdir $TMP_DIR/loramiso/fs
1634 cd $TMP_DIR/loramiso/fs
1635 for i in $( ls ../boot/root* | sort -r ) ; do
1636 uncompress $i | cpio -idmu
1637 rm -f $i
1638 done
1639 mkdir -p $TMP_DIR/loramiso/fs/mnt/.cdrom
1640 cd - >/dev/null
1641 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1642 unmeta_boot
1643 VOLUM_NAME="SliTaz_LoRAM_CDROM"
1644 sed -i "s|root=|isofs= rodev=/dev/cdrom/fs &|;s/.ive/cdrom/" \
1645 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1646 sed -i '/LABEL slitaz/{NNNNp;s|z cdrom|& text|;s|L slitaz|&text|;s|root=|screen=text &|;s|,[^ ]*||}' \
1647 $TMP_DIR/loramiso/boot/isolinux/*.cfg
1648 create_iso $OUTPUT $TMP_DIR/loramiso
1652 # Create http bootstrap to load and remove loram_cdrom
1653 # Meta flavors are converted to normal flavors.
1655 build_loram_http() {
1656 build_initfs http || return 1
1657 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1658 cleanup_efi_boot $TMP_DIR/loramiso
1659 rm -f $TMP_DIR/loramiso/boot/rootfs*
1660 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1661 unmeta_boot
1662 create_iso $OUTPUT $TMP_DIR/loramiso
1666 # Update meta flavor selection sizes.
1667 # Reduce sizes with rootfs gains.
1669 update_metaiso_sizes() {
1670 [ -s $TMP_DIR/loramiso/boot/rootfs0.gz ] &&
1671 sed -i 's|rootfs.gz|&,/boot/rootfs0.gz|' $TMP_DIR/loramiso/boot/isolinux/*.cfg
1672 for cfg in $(grep -El '(append|ifmem) [0-9]' $TMP_DIR/loramiso/boot/isolinux/*.cfg)
1673 do
1674 local append="$(grep -E '(append|ifmem) [0-9]' $cfg)"
1675 local sizes="$rootfs_sizes"
1676 local new
1677 set -- $append
1678 shift
1679 [ "$1" = "ifmem" ] && shift
1680 new=""
1681 while [ -n "$2" ]; do
1682 local s
1683 case "$1" in
1684 *G) s=$(( ${1%G} * 1024 * 1024 ));;
1685 *M) s=$(( ${1%M} * 1024 ));;
1686 *) s=${1%K};;
1687 esac
1688 sizes=${sizes#* }
1689 for i in $sizes ; do
1690 s=$(( $s - $i ))
1691 done
1692 new="$new $s $2"
1693 shift 2
1694 done
1695 sed -i -e "/append [0-9]/s/append .*/append$new $1/" -e \
1696 "/append ifmem [0-9]/s/append .*/append ifmem$new $1/" $cfg
1697 sed -i 's|\(initrd=\)\([^r]*\)\(rootfs\)|\1\2rootfs.gz,\2\3|' $cfg
1698 sed -i '/LABEL base/{NNNNp;s|base .ive|cdrom|;s|base|cdrom|;s|,[^ ]*||}' $cfg
1699 sed -i '/LABEL cdrom/{NNNNp;s|z cdrom|& text|;s|L cdrom|&text|;s|root=|screen=text &|;s|,[^ ]*||}' $cfg
1700 done
1704 # Move rootfs to a squashfs filesystem into the initramfs writeable with aufs/overlayfs.
1705 # Meta flavor selection sizes are updated.
1707 build_loram_ram() {
1708 build_initfs ram || return 1
1709 build_loram_rootfs "$1"
1710 cp -a $TMP_DIR/iso $TMP_DIR/loramiso
1711 cleanup_efi_boot $TMP_DIR/loramiso
1712 mv $TMP_DIR/initfs.gz $TMP_DIR/loramiso/boot/rootfs.gz
1713 cp $TMP_DIR/rootfs* $TMP_DIR/loramiso/boot
1714 update_metaiso_sizes
1715 create_iso $OUTPUT $TMP_DIR/loramiso
1719 # Remove files installed by packages
1721 find_flavor_rootfs() {
1722 for i in $1/etc/tazlito/*.extract; do
1723 [ -e $i ] || continue
1724 chroot $1 /bin/sh ${i#$1}
1725 done
1727 # Clean hardlinks and files patched by genisofs in /boot
1728 for i in isolinux/isolinux.bin isolinux/boot.cat bzImage ; do
1729 rm -f $1/boot/$i*
1730 done
1732 # Clean files generated in post_install
1733 rm -f $1/lib/modules/*/modules.* $1/etc/mtab \
1734 $1/dev/core $1/dev/fd $1/dev/std*
1736 # Verify md5
1737 cat $1$INSTALLED/*/md5sum | \
1738 while read md5 file; do
1739 [ -e "$1$file" ] || continue
1740 [ "$(md5sum < "$1$file")" = "$md5 -" ] &&
1741 rm -f "$1$file"
1742 done
1744 # Check configuration files
1745 for i in $1$INSTALLED/*/volatile.cpio.gz; do
1746 [ -e $i ] || continue
1747 mkdir /tmp/volatile$$
1748 zcat $i | ( cd /tmp/volatile$$ ; cpio -idmu > /dev/null 2>&1 )
1749 ( cd /tmp/volatile$$ ; find * -type f 2> /dev/null) | \
1750 while read file ; do
1751 [ -e "$1/$file" ] || continue
1752 cmp -s "/tmp/volatile$$/$file" "$1/$file" && rm -f "$1/$file"
1753 done
1754 rm -rf /tmp/volatile$$
1755 done
1757 # Remove other files blindly
1758 for i in $1$INSTALLED/*/files.list; do
1759 for file in $(cat "$i"); do
1760 [ "$1$file" -nt "$i" ] && continue
1761 [ -f "$1$file" -a ! -L "$1$file" ] && continue
1762 [ -d "$1$file" ] || rm -f "$1$file"
1763 done
1764 done
1766 # Remove tazpkg files and tmp files
1767 rm -rf $1$INSTALLED* $1/tmp $1/var/tmp
1768 rm -f $1$LOCALSTATE/*packages* $1$LOCALSTATE/files.list.lzma \
1769 $1$LOCALSTATE/mirror* $1/var/cache/*/* \
1770 $1/var/lock/* $1/var/log/* $1/var/run/* $1/var/run/*/* \
1771 $1/var/lib/* $1/var/lib/dbus/* 2>/dev/null
1773 # Cleanup directory tree
1774 cd $1
1775 find * -type d | sort -r | while read dir; do
1776 rmdir "$dir" 2>/dev/null
1777 done
1778 cd - > /dev/null
1782 # Get byte(s) from a binary file
1784 get() {
1785 od -v -j $1 -N ${3:-2} -t u${3:-2} -w${3:-2} -An $2 2>/dev/null | sed 's/ *//'
1789 # Get cpio flavor info from the ISO image
1791 flavordata() {
1792 [ $(get 1024 $1) -eq 35615 ] && n=2 || n=$((1+$(get 417 $1 1)))
1793 dd if=$1 bs=512 skip=$n count=20 2>/dev/null | zcat 2>/dev/null
1797 # Restore undigest mirrors
1799 restore_mirrors() {
1800 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1801 [ -d "$undigest.bak" ] || [ -e "$priority.bak" ] || return
1803 action 'Restoring mirrors...'
1804 if [ -d "$undigest.bak" ]; then
1805 [ -d "$undigest" ] && rm -r "$undigest"
1806 mv "$undigest.bak" "$undigest"
1807 fi
1808 [ -e "$priority.bak" ] && mv -f "$priority.bak" "$priority"
1809 :; status
1813 # Setup undigest mirrors
1815 setup_mirrors() {
1816 # Setup mirrors in plain system or in chroot (with variable root=)
1817 local mirrorlist="$1" fresh repacked
1818 local undigest="$root$LOCALSTATE/undigest" priority="$root$LOCALSTATE/priority"
1820 # Restore mirrors first: in case of non-clear exits, hangs, etc.
1821 restore_mirrors
1823 _ 'Setting up mirrors for %s...' "$root/"
1824 # Backing up current undigest mirrors and priority
1825 [ -d "$undigest" ] && mv "$undigest" "$undigest.bak"
1826 [ -e "$priority" ] && mv "$priority" "$priority.bak"
1827 rm -rf '/var/www/tazlito/'
1828 mkdir -p '/var/www/tazlito/'
1830 # Packages produced by CookUtils: on Tank or local, or repacked packages: highest priority
1831 fresh='/home/slitaz/packages'
1832 if [ -d "$fresh" ]; then
1833 # Setup first undigest mirror
1834 mkdir -p "$undigest/fresh"
1835 echo "$fresh" > "$undigest/fresh/mirror"
1836 echo 'fresh' >> "$priority"
1837 # Rebuild mirror DB if needed
1838 [ ! -e "$fresh/IDs" ] && tazpkg mkdb "$fresh" --forced --root=''
1839 [ -n "$(find -L "$fresh" -name '*.tazpkg' -newer "$fresh/IDs")" ] && \
1840 tazpkg mkdb "$fresh" --forced --root=''
1841 cp -a "$fresh/files.list.lzma" "$fresh/files-list.lzma"
1842 fi
1844 # Repacked packages: high priority
1845 repacked="$PACKAGES_REPOSITORY"
1846 if [ -d "$repacked" -a "$repacked" != "$fresh" ] && ls "$repacked" | grep -q ".tazpkg"; then
1847 # According to Tazlito setup file (tazlito.conf):
1848 # WORK_DIR="/home/slitaz/$SLITAZ_VERSION"
1849 # or
1850 # WORK_DIR="/home/slitaz"
1851 # and
1852 # PACKAGES_REPOSITORY="$WORK_DIR/packages"
1853 # It MAY or MAY NOT match /home/slitaz/packages, so here we setup second repository
1855 # Setup second undigest mirror
1856 mkdir -p "$undigest/repacked"
1857 echo "$repacked" > "$undigest/repacked/mirror"
1858 echo 'repacked' >> "$priority"
1859 # Rebuild mirror DB if needed
1860 [ ! -e "$repacked/IDs" ] && tazpkg mkdb "$repacked" --forced --root=''
1861 [ -n "$(find -L "$repacked" -name '*.tazpkg' -newer "$repacked/IDs")" ] && \
1862 tazpkg mkdb "$repacked" --forced --root=''
1863 cp -a "$repacked/files.list.lzma" "$repacked/files-list.lzma"
1864 fi
1866 # All repositories listed in mirrors list: normal priority
1867 [ -e "$mirrorlist" ] && \
1868 while read mirror; do
1869 # Provide consistent mirror ID for caching purpose: /var/cache/tazpkg/<mirror ID>/packages
1870 mirrorid=$(echo "$mirror" | md5sum | cut -d' ' -f1)
1871 mkdir -p "$undigest/$mirrorid"
1872 echo "$mirror" > "$undigest/$mirrorid/mirror"
1873 echo "$mirrorid" >> "$priority"
1874 done < "$mirrorlist"
1876 # And, finally, main mirror with the lowest (failsafe) priority (nothing to do)
1878 # Show list of mirrors
1879 [ -f "$priority" ] && awk -vdb="$root$LOCALSTATE" '
1880 function show(num, name, url) {
1881 printf " %-1.1d. %32.32s %-44.44s\n", num, name " ...............................", url;
1884 num++;
1885 "cat " db "/undigest/" $0 "/mirror" | getline url;
1886 show(num, $0, url);
1888 END {
1889 num++;
1890 "cat " db "/mirror" | getline url;
1891 show(num, "main", url);
1892 }' "$priority"
1894 tazpkg recharge --quiet >/dev/null
1898 # Get list of 'packages.info' lists using priority
1900 pi_lists() {
1901 local pi
1902 [ -s "$root$LOCALSTATE/packages.info" ] || tazpkg recharge --root="$root" >/dev/null 2>&1
1903 local priority="$root$LOCALSTATE/priority"
1904 local undigest="$root$LOCALSTATE/undigest"
1907 [ -s "$priority" ] && cat "$priority"
1908 echo 'main'
1909 [ -d "$undigest" ] && ls "$undigest"
1910 } | awk -vun="$undigest/" '
1912 if (arr[$0] != 1) {
1913 arr[$0] = 1;
1914 print un $0 "/packages.info";
1916 }' | sed 's|/undigest/main||' | \
1917 while read pi; do
1918 [ -e "$pi" ] && echo "$pi"
1919 done
1923 # Strip versions from packages list
1925 strip_versions() {
1926 if [ -n "$stripped" ]; then
1927 action 'Consider list %s already stripped' "$(basename "$1")"
1928 status
1929 return 0
1930 fi
1931 action 'Strip versions from list %s...' "$(basename "$1")"
1932 local in_list="$1" tmp_list="$(mktemp)" namever pkg
1933 [ -f "$in_list" ] || die "List '$in_list' not found."
1935 # $pkg=<name>-<version> or $pkg=<name>; both <name> and <version> may contain dashes
1936 awk '
1938 if (FILENAME ~ "packages.info") {
1939 # Collect package names
1940 FS = "\t"; pkg[$1] = 1;
1941 } else {
1942 FS = OFS = "-"; $0 = $0; # Fix bug with FS for first record
1943 while (NF > 1 && ! pkg[$0])
1944 NF --;
1945 printf "%s\n", $0;
1947 }' $(pi_lists) "$in_list" > "$tmp_list"
1949 cat "$tmp_list" > "$in_list"
1950 rm "$tmp_list"
1951 status
1955 # Display list of unknown packages (informative)
1957 display_unknown() {
1958 [ -s "$1" ] || return
1959 echo "Unknown packages:" >&2
1960 cat "$1" >&2
1961 rm "$1"
1965 # Display warnings about critical packages absent (informative)
1967 display_warn() {
1968 [ -s "$1" ] || return
1969 echo "Absent critical packages:" >&2
1970 cat "$1" >&2
1971 rm "$1"
1972 echo "Probably ISO image will be unusable."
1976 # Install packages to rootfs
1978 install_list_to_rootfs() {
1979 local list="$1" rootfs="$2" pkg i ii
1980 local undigest="$rootfs/var/lib/tazpkg/undigest"
1982 # initial tazpkg setup in empty rootfs
1983 tazpkg --root=$rootfs >/dev/null 2>&1
1984 # pass current 'mirror' to the rootfs
1985 mkdir -p $rootfs/var/lib/tazpkg $rootfs/etc
1986 cp -f /var/lib/tazpkg/mirror $rootfs/var/lib/tazpkg/mirror
1987 cp -f /etc/slitaz-release $rootfs/etc/slitaz-release
1988 # link rootfs packages cache to the regular packages cache
1989 rm -r "$rootfs/var/cache/tazpkg"
1990 ln -s /var/cache/tazpkg "$rootfs/var/cache/tazpkg"
1992 setup_mirrors mirrors
1994 # Just in case if flavor doesn't contain "tazlito" package
1995 mkdir -p "$rootfs/etc/tazlito"
1997 newline
1999 # Choose detailed log with --detailed
2000 if [ -n "$detailed" ]; then
2001 while read pkg; do
2002 separator '-'
2003 echo $pkg
2004 tazpkg -gi $pkg --root=$rootfs --local --quiet --cookmode | tee -a $log
2005 done < $list
2006 separator '='
2007 else
2008 while read pkg; do
2009 action 'Installing package: %s' "$pkg"
2010 yes y | tazpkg -gi $pkg --root=$rootfs --quiet >> $log || exit 1
2011 status
2012 done < $list
2013 fi
2014 newline
2016 restore_mirrors
2017 # Remove 'fresh' and 'repacked' undigest repos leaving all other
2018 for i in fresh repacked; do
2019 ii="$undigest/$i"
2020 [ -d "$ii" ] && rm -rf "$ii"
2021 ii="$rootfs/var/lib/tazpkg/priority"
2022 if [ -f "$ii" ]; then
2023 sed -i "/$i/d" "$ii"
2024 [ -s "$ii" ] || rm "$ii"
2025 fi
2026 done
2027 [ -d "$undigest" ] && \
2028 for i in $(find "$undigest" -type f); do
2029 # Remove all undigest PKGDB files but 'mirror'
2030 [ "$(basename "$i")" != 'mirror' ] && rm "$i"
2031 done
2032 [ -d "$undigest" ] && \
2033 rmdir --ignore-fail-on-non-empty "$undigest"
2035 # Un-link packages cache
2036 rm "$rootfs/var/cache/tazpkg"
2038 # Clean /var/lib/tazpkg
2039 (cd $rootfs/var/lib/tazpkg; rm ID* descriptions.txt extra.list files* packages.* 2>/dev/null)
2045 ####################
2046 # Tazlito commands #
2047 ####################
2049 # /usr/bin/tazlito is linked with /usr/bin/reduplicate and /usr/bin/deduplicate
2050 case "$0" in
2051 *reduplicate)
2052 find ${@:-.} ! -type d -links +1 \
2053 -exec cp -a {} {}$$ \; -exec mv {}$$ {} \;
2054 exit 0 ;;
2055 *deduplicate)
2056 deduplicate "$@"
2057 exit 0 ;;
2058 esac
2061 case "$COMMAND" in
2062 stats)
2063 # Tazlito general statistics from the config file.
2065 title 'Tazlito statistics'
2066 optlist "\
2067 Config file : $CONFIG_FILE
2068 ISO name : $ISO_NAME.iso
2069 Volume name : $VOLUM_NAME
2070 Prepared : $PREPARED
2071 Packages repository : $PACKAGES_REPOSITORY
2072 Distro directory : $DISTRO
2073 Additional files : $ADDFILES
2074 " | sed '/: $/d'
2075 footer
2076 ;;
2079 list-addfiles)
2080 # Simple list of additional files in the rootfs
2081 newline
2082 if [ -d "$ADDFILES/rootfs" ]; then
2083 cd $ADDFILES
2084 find rootfs -type f
2085 else
2086 _ 'Additional files not found: %s' "$ADDFILES/rootfs/"
2087 fi
2088 newline
2089 ;;
2092 gen-config)
2093 # Generate a new config file in the current dir or the specified
2094 # directory by $2.
2096 if [ -n "$2" ]; then
2097 mkdir -p "$2" && cd "$2"
2098 fi
2100 newline
2101 action 'Generating empty tazlito.conf...'
2102 empty_config_file
2103 status
2105 separator
2106 if [ -f 'tazlito.conf' ] ; then
2107 _ 'Configuration file is ready to edit.'
2108 _ 'File location: %s' "$(pwd)/tazlito.conf"
2109 newline
2110 fi
2111 ;;
2114 configure)
2115 # Configure a tazlito.conf config file. Start by getting
2116 # a empty config file and sed it.
2118 if [ -f 'tazlito.conf' ]; then
2119 rm tazlito.conf
2120 else
2121 [ $(id -u) -ne 0 ] && die 'You must be root to configure the main config file' \
2122 'or in the same directory of the file you want to configure.'
2123 cd /etc
2124 fi
2126 empty_config_file
2128 title 'Configuring: %s' "$(pwd)/tazlito.conf"
2130 # ISO name.
2131 echo -n "ISO name : " ; read answer
2132 sed -i s#'ISO_NAME=\"\"'#"ISO_NAME=\"$answer\""# tazlito.conf
2133 # Volume name.
2134 echo -n "Volume name : " ; read answer
2135 sed -i s/'VOLUM_NAME=\"SliTaz\"'/"VOLUM_NAME=\"$answer\""/ tazlito.conf
2136 # Packages repository.
2137 echo -n "Packages repository : " ; read answer
2138 sed -i s#'PACKAGES_REPOSITORY=\"\"'#"PACKAGES_REPOSITORY=\"$answer\""# tazlito.conf
2139 # Distro path.
2140 echo -n "Distro path : " ; read answer
2141 sed -i s#'DISTRO=\"\"'#"DISTRO=\"$answer\""# tazlito.conf
2142 footer "Config file is ready to use."
2143 echo 'You can now extract an ISO or generate a distro.'
2144 newline
2145 ;;
2148 gen-iso)
2149 # Simply generate a new iso.
2151 check_root
2152 verify_rootcd
2153 gen_livecd_isolinux
2154 distro_stats
2155 ;;
2158 gen-initiso)
2159 # Simply generate a new initramfs with a new iso.
2161 check_root
2162 verify_rootcd
2163 gen_initramfs "$ROOTFS"
2164 gen_livecd_isolinux
2165 distro_stats
2166 ;;
2169 extract-distro|extract-iso)
2170 # Extract an ISO image to a directory and rebuild the LiveCD tree.
2172 check_root
2173 ISO_IMAGE="$2"
2174 [ -z "$ISO_IMAGE" ] && die 'Please specify the path to the ISO image.' \
2175 'Example:\n tazlito image.iso /path/target'
2177 # Set the distro path by checking for $3 on cmdline.
2178 TARGET="${3:-$DISTRO}"
2180 # Exit if existing distro is found.
2181 [ -d "$TARGET/rootfs" ] && die "A rootfs exists in '$TARGET'." \
2182 'Please clean the distro tree or change directory path.'
2184 title 'Tazlito extracting: %s' "$(basename $ISO_IMAGE)"
2186 # Start to mount the ISO.
2187 action 'Mounting ISO image...'
2188 mkdir -p "$TMP_DIR"
2189 # Get ISO file size.
2190 isosize=$(du -sh "$ISO_IMAGE" | cut -f1)
2191 mount -o loop -r "$ISO_IMAGE" "$TMP_DIR"
2192 sleep 2
2193 # Prepare target dir, copy the kernel and the rootfs.
2194 mkdir -p "$TARGET/rootfs" "$TARGET/rootcd/boot"
2195 status
2197 action 'Copying the Linux kernel...'
2198 if cp $TMP_DIR/boot/vmlinuz* "$TARGET/rootcd/boot" 2>/dev/null; then
2199 make_bzImage_hardlink "$TARGET/rootcd/boot"
2200 else
2201 cp "$TMP_DIR/boot/bzImage" "$TARGET/rootcd/boot"
2202 fi
2203 status
2205 for i in $(ls $TMP_DIR); do
2206 [ "$i" = 'boot' ] && continue
2207 cp -a "$TMP_DIR/$i" "$TARGET/rootcd"
2208 done
2210 for loader in isolinux syslinux extlinux grub; do
2211 [ -d "$TMP_DIR/boot/$loader" ] || continue
2212 action 'Copying %s files...' "$loader"
2213 cp -a "$TMP_DIR/boot/$loader" "$TARGET/rootcd/boot"
2214 status
2215 done
2217 action 'Copying the rootfs...'
2218 cp $TMP_DIR/boot/rootfs*.?z* "$TARGET/rootcd/boot"
2219 status
2221 cleanup_efi_boot "$TARGET/rootcd"
2223 # Extract initramfs.
2224 cd "$TARGET/rootfs"
2225 action 'Extracting the rootfs...'
2226 for i in $(ls -r $TARGET/rootcd/boot/rootfs*z); do
2227 extract_rootfs "$i" "$TARGET/rootfs"
2228 done
2229 # unpack /usr
2230 for i in etc/tazlito/*.extract; do
2231 [ -f "$i" ] && . $i ../rootcd
2232 done
2233 # Umount and remove temp directory and cd to $TARGET to get stats.
2234 umount "$TMP_DIR" && rm -rf "$TMP_DIR"
2235 cd ..
2236 status
2238 newline
2239 separator
2240 echo "Extracted : $(basename $ISO_IMAGE) ($isosize)"
2241 echo "Distro tree : $(pwd)"
2242 echo "Rootfs size : $(du -sh rootfs)"
2243 echo "Rootcd size : $(du -sh rootcd)"
2244 footer
2245 ;;
2248 list-flavors)
2249 # Show available flavors.
2250 list='/etc/tazlito/flavors.list'
2251 [ ! -s $list -o -n "$recharge" ] && download flavors.list -O - > $list
2252 title 'List of flavors'
2253 cat $list
2254 footer
2255 ;;
2258 show-flavor)
2259 # Show flavor descriptions.
2260 set -e
2261 flavor=${2%.flavor}
2262 flv_dir="$(extract_flavor "$flavor")"
2263 desc="$flv_dir/$flavor.desc"
2264 if [ -n "$brief" ]; then
2265 if [ -z "$noheader" ]; then
2266 printf "%-16.16s %6.6s %6.6s %s\n" 'Name' 'ISO' 'Rootfs' 'Description'
2267 separator
2268 fi
2269 printf "%-16.16s %6.6s %6.6s %s\n" "$flavor" \
2270 "$(field ISO "$desc")" \
2271 "$(field Rootfs "$desc")" \
2272 "$(field Description "$desc")"
2273 else
2274 separator
2275 cat "$desc"
2276 fi
2277 cleanup
2278 ;;
2281 gen-liveflavor)
2282 # Generate a new flavor from the live system.
2283 FLAVOR=${2%.flavor}
2284 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2286 case "$FLAVOR" in
2287 -?|-h*|--help)
2288 cat <<EOT
2289 SliTaz Live Tool - Version: $VERSION
2291 $(boldify 'Usage:') tazlito gen-liveflavor <flavor-name> [<flavor-patch-file>]
2293 $(boldify '<flavor-patch-file> format:')
2294 $(optlist "\
2295 code data
2296 + package to add
2297 - package to remove
2298 ! non-free package to add
2299 ? display message
2300 @ flavor description
2301 ")
2303 $(boldify 'Example:')
2304 $(optlist "\
2305 @ Developer tools for SliTaz maintainers
2306 + slitaz-toolchain
2307 + mercurial
2308 ")
2309 EOT
2310 exit 1
2311 ;;
2312 esac
2313 mv /etc/tazlito/distro-packages.list \
2314 /etc/tazlito/distro-packages.list.$$ 2>/dev/null
2315 rm -f distro-packages.list non-free.list 2>/dev/null
2316 tazpkg recharge
2318 DESC=""
2319 [ -n "$3" ] && \
2320 while read action pkg; do
2321 case "$action" in
2322 +) yes | tazpkg get-install $pkg 2>&1 >> $log || exit 1 ;;
2323 -) yes | tazpkg remove $pkg ;;
2324 !) echo $pkg >> non-free.list ;;
2325 @) DESC="$pkg" ;;
2326 \?) echo -en "$pkg"; read action ;;
2327 esac
2328 done < $3
2330 yes '' | tazlito gen-distro
2331 echo "$DESC" | tazlito gen-flavor "$FLAVOR"
2332 mv /etc/tazlito/distro-packages.list.$$ \
2333 /etc/tazlito/distro-packages.list 2>/dev/null
2334 ;;
2337 gen-flavor)
2338 # Generate a new flavor from the last ISO image generated
2339 FLAVOR=${2%.flavor}
2340 [ -z "$FLAVOR" ] && die 'Please specify flavor name on the commandline.'
2342 title 'Flavor generation'
2343 check_rootfs
2344 FILES="$FLAVOR.pkglist"
2346 action 'Creating file %s...' "$FLAVOR.flavor"
2347 for i in rootcd rootfs; do
2348 if [ -d "$ADDFILES/$i" ] ; then
2349 FILES="$FILES\n$FLAVOR.$i"
2350 ( cd "$ADDFILES/$i"; find . ) | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.$i
2351 fi
2352 done
2353 status
2355 answer=$(grep -s ^Description $FLAVOR.desc)
2356 answer=${answer#Description : }
2357 if [ -z "$answer" ]; then
2358 echo -n "Description: "
2359 read answer
2360 fi
2362 action 'Compressing flavor %s...' "$FLAVOR"
2363 echo "Flavor : $FLAVOR" > $FLAVOR.desc
2364 echo "Description : $answer" >> $FLAVOR.desc
2365 (cd $DISTRO; distro_sizes) >> $FLAVOR.desc
2366 \rm -f $FLAVOR.pkglist $FLAVOR.nonfree 2>/dev/null
2367 for i in $(ls $ROOTFS$INSTALLED); do
2368 eval $(grep ^VERSION= $ROOTFS$INSTALLED/$i/receipt)
2369 EXTRAVERSION=""
2370 eval $(grep ^EXTRAVERSION= $ROOTFS$INSTALLED/$i/receipt)
2371 eval $(grep ^CATEGORY= $ROOTFS$INSTALLED/$i/receipt)
2372 if [ "$CATEGORY" = 'non-free' -a "${i%%-*}" != 'get' ]; then
2373 echo "$i" >> $FLAVOR.nonfree
2374 else
2375 echo "$i-$VERSION$EXTRAVERSION" >> $FLAVOR.pkglist
2376 fi
2377 done
2378 [ -s $FLAVOR.nonfree ] && $FILES="$FILES\n$FLAVOR.nonfree"
2379 for i in $LOCALSTATE/undigest/*/mirror ; do
2380 [ -s $i ] && cat $i >> $FLAVOR.mirrors
2381 done
2382 [ -s $FLAVOR.mirrors ] && $FILES="$FILES\n$FLAVOR.mirrors"
2383 touch -t 197001010100.00 $FLAVOR.*
2384 echo -e "$FLAVOR.desc\n$FILES" | cpio -o -H newc 2>/dev/null | dogzip $FLAVOR.flavor
2385 rm $(echo -e $FILES)
2386 status
2388 footer "Flavor size: $(du -sh $FLAVOR.flavor)"
2389 ;;
2392 upgrade-flavor)
2393 # Strip versions from pkglist and update estimated numbers in flavor.desc
2394 flavor="${2%.flavor}"
2395 set -e
2396 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2397 set +e
2399 flv_dir="$(extract_flavor "$flavor")"
2401 strip_versions "$flv_dir/$flavor.pkglist"
2403 action 'Updating %s...' "$flavor.desc"
2405 [ -f "$flv_dir/$flavor.mirrors" ] && setup_mirrors "$flv_dir/$flavor.mirrors" >/dev/null
2406 set -- $(module calc_sizes "$flv_dir" "$flavor")
2407 restore_mirrors >/dev/null
2409 sed -i -e '/Image is ready/d' \
2410 -e "s|\(Rootfs size *:\).*$|\1 $1 (estimated)|" \
2411 -e "s|\(Initramfs size *:\).*$|\1 $2 (estimated)|" \
2412 -e "s|\(ISO image size *:\).*$|\1 $3 (estimated)|" \
2413 -e "s|\(Packages *:\).*$|\1 $4|" \
2414 -e "s|\(Build date *:\).*$|\1 $(date '+%Y%m%d at %T')|" \
2415 "$flv_dir/$flavor.desc"
2417 pack_flavor "$flv_dir" "$flavor"
2418 status
2419 display_unknown "$flv_dir/err"
2420 display_warn "$flv_dir/warn"
2421 cleanup
2422 ;;
2425 extract-flavor)
2426 # Extract a flavor into $FLAVORS_REPOSITORY
2427 flavor="${2%.flavor}"
2428 set -e
2429 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2430 set +e
2432 action 'Extracting %s...' "$flavor.flavor"
2433 flv_dir="$(extract_flavor "$flavor" full)"
2434 storage="$FLAVORS_REPOSITORY/$flavor"
2436 rm -rf "$storage" 2>/dev/null
2437 mkdir -p "$storage"
2438 cp -a "$flv_dir"/* "$storage"
2439 rm "$storage/description"
2440 status
2442 strip_versions "$storage/packages.list"
2444 cleanup
2445 ;;
2448 pack-flavor)
2449 # Create a flavor from $FLAVORS_REPOSITORY.
2450 flavor=${2%.flavor}
2451 storage="$FLAVORS_REPOSITORY/$flavor"
2453 [ -s "$storage/receipt" ] || die "No $flavor receipt in $FLAVORS_REPOSITORY."
2455 action 'Creating flavor %s...' "$flavor"
2456 tmp_dir="$(mktemp -d)"
2458 while read from to; do
2459 [ -s "$storage/$from" ] || continue
2460 cp -a "$storage/$from" "$tmp_dir/$to"
2461 done <<EOT
2462 mirrors $flavor.mirrors
2463 distro.sh $flavor-distro.sh
2464 receipt $flavor.receipt
2465 non-free.list $flavor.nonfree
2466 EOT
2468 # Build the package list.
2469 # It can include a list from another flavor with the keyword @include
2470 if [ -s "$storage/packages.list" ]; then
2471 include=$(grep '^@include' "$storage/packages.list")
2472 if [ -n "$include" ]; then
2473 include=${include#@include }
2474 if [ -s "$FLAVORS_REPOSITORY/$include/packages.list" ]; then
2475 cp -f "$FLAVORS_REPOSITORY/$include/packages.list" "$tmp_dir/$flavor.pkglist"
2476 else
2477 echo -e "\nERROR: Can't find include package list from $include\n"
2478 fi
2479 fi
2480 # Generate the final/initial package list
2481 [ -s "$storage/packages.list" ] && \
2482 cat "$storage/packages.list" >> "$tmp_dir/$flavor.pkglist"
2483 sed -i '/@include/d' "$tmp_dir/$flavor.pkglist"
2484 fi
2486 if grep -q ^ROOTFS_SELECTION "$storage/receipt"; then
2487 # Process multi-rootfs flavor
2488 . "$storage/receipt"
2489 set -- $ROOTFS_SELECTION
2490 [ -n "$FRUGAL_RAM" ] || FRUGAL_RAM=$1
2491 [ -f "$FLAVORS_REPOSITORY/$2/packages.list" ] || tazlito extract-flavor $2
2492 cp "$FLAVORS_REPOSITORY/$2/packages.list" "$tmp_dir/$flavor.pkglist"
2494 for i in rootcd rootfs; do
2495 mkdir "$tmp_dir/$i"
2496 # Copy extra files from the first flavor
2497 [ -d "$FLAVORS_REPOSITORY/$2/$i" ] &&
2498 cp -a "$FLAVORS_REPOSITORY/$2/$i" "$tmp_dir"
2499 # Overload extra files by meta flavor
2500 [ -d "$storage/$i" ] && cp -a "$storage/$i" "$tmp_dir"
2501 [ -n "$(ls $tmp_dir/$i)" ] &&
2502 (cd "$tmp_dir/$i"; find . | cpio -o -H newc 2>/dev/null ) | \
2503 dogzip "$tmp_dir/$flavor.$i"
2504 rm -rf "$tmp_dir/$i"
2505 done
2506 else
2507 # Process plain flavor
2508 for i in rootcd rootfs; do
2509 [ -d "$storage/$i" ] || continue
2510 (cd "$storage/$i";
2511 find . | cpio -o -H newc 2>/dev/null) | dogzip "$tmp_dir/$flavor.$i"
2512 done
2513 fi
2515 unset VERSION MAINTAINER ROOTFS_SELECTION
2516 set -- $(module calc_sizes "$tmp_dir" "$flavor")
2517 ROOTFS_SIZE="$1 (estimated)"
2518 INITRAMFS_SIZE="$2 (estimated)"
2519 ISO_SIZE="$3 (estimated)"
2520 PKGNUM="$4"
2521 . "$storage/receipt"
2523 sed '/: $/d' > "$tmp_dir/$flavor.desc" <<EOT
2524 Flavor : $FLAVOR
2525 Description : $SHORT_DESC
2526 Version : $VERSION
2527 Maintainer : $MAINTAINER
2528 LiveCD RAM size : $FRUGAL_RAM
2529 Rootfs list : $ROOTFS_SELECTION
2530 Build date : $(date '+%Y%m%d at %T')
2531 Packages : $PKGNUM
2532 Rootfs size : $ROOTFS_SIZE
2533 Initramfs size : $INITRAMFS_SIZE
2534 ISO image size : $ISO_SIZE
2535 ================================================================================
2537 EOT
2539 rm -f $tmp_dir/packages.list
2540 pack_flavor "$tmp_dir" "$flavor"
2541 status
2542 display_unknown "$tmp_dir/err"
2543 display_warn "$flv_dir/warn"
2544 cleanup
2545 ;;
2548 get-flavor)
2549 # Get a flavor's files and prepare for gen-distro.
2550 flavor=${2%.flavor}
2551 title 'Preparing %s distro flavor' "$flavor"
2552 set -e
2553 [ -f "$flavor.flavor" ] || download "$flavor.flavor"
2554 set +e
2556 action 'Cleaning %s...' "$DISTRO"
2557 [ -d "$DISTRO" ] && rm -r "$DISTRO"
2558 # Clean old files
2559 for i in non-free.list distro-packages.list distro.sh receipt mirrors err; do
2560 [ -f "$i" ] && rm "$i"
2561 done
2562 mkdir -p "$DISTRO"
2563 status
2565 [ -z "$noup" ] && tazlito upgrade-flavor "$flavor.flavor"
2567 action 'Extracting flavor %s...' "$flavor.flavor"
2568 flv_dir="$(extract_flavor "$flavor" info)"
2569 cp -a "$flv_dir"/* .
2570 mv packages.list distro-packages.list
2571 mv -f info /etc/tazlito
2572 status
2574 for i in rootcd rootfs; do
2575 if [ -d "$i" ]; then
2576 mkdir -p "$ADDFILES"; mv "$i" "$ADDFILES/$i"
2577 fi
2578 done
2580 sed '/^Rootfs list/!d;s/.*: //' description > /etc/tazlito/rootfs.list
2581 [ -s /etc/tazlito/rootfs.list ] || rm -f /etc/tazlito/rootfs.list
2583 action 'Updating %s...' 'tazlito.conf'
2584 [ -f tazlito.conf ] || cp /etc/tazlito/tazlito.conf .
2585 grep -v "^#VOLUM_NAME" < tazlito.conf | \
2586 sed "s/^VOLUM_NA/VOLUM_NAME=\"SliTaz $flavor\"\\n#VOLUM_NA/" \
2587 > tazlito.conf.$$ && mv tazlito.conf.$$ tazlito.conf
2588 sed -i "s/ISO_NAME=.*/ISO_NAME=\"slitaz-$flavor\"/" tazlito.conf
2589 status
2591 footer 'Flavor is ready to be generated by `tazlito gen-distro`'
2592 cleanup
2593 ;;
2596 iso2flavor)
2597 [ -z "$3" -o ! -s "$2" ] && die 'Usage: tazlito iso2flavor <image.iso> <flavor_name>' \
2598 '\n\nCreate a file <flavor_name>.flavor from the CD-ROM image file <image.iso>'
2600 FLAVOR=${3%.flavor}
2601 mkdir -p $TMP_DIR/iso $TMP_DIR/rootfs $TMP_DIR/flavor
2602 mount -o loop,ro $2 $TMP_DIR/iso
2603 flavordata $2 | (cd $TMP_DIR/flavor; cpio -i 2>/dev/null)
2604 if [ -s $TMP_DIR/iso/boot/rootfs1.gz -a \
2605 ! -s $TMP_DIR/flavor/*.desc ]; then
2606 _ 'META flavors are not supported.'
2607 umount -d $TMP_DIR/iso
2608 elif [ ! -s $TMP_DIR/iso/boot/rootfs.gz -a \
2609 ! -s $TMP_DIR/iso/boot/rootfs1.gz ]; then
2610 _ 'No %s in ISO image. Needs a SliTaz ISO.' '/boot/rootfs.gz'
2611 umount -d $TMP_DIR/iso
2612 else
2613 for i in $(ls -r $TMP_DIR/iso/boot/rootfs*z); do
2614 uncompress $i | \
2615 ( cd $TMP_DIR/rootfs ; cpio -idmu > /dev/null 2>&1 )
2616 done
2617 if [ ! -s $TMP_DIR/rootfs/etc/slitaz-release ]; then
2618 _ 'No file %s in %s of ISO image. Needs a non-loram SliTaz ISO.' \
2619 '/etc/slitaz-release' '/boot/rootfs.gz'
2620 umount -d $TMP_DIR/iso
2621 else
2622 ROOTFS_SIZE=$(du -hs $TMP_DIR/rootfs | awk '{ print $1 }')
2623 RAM_SIZE=$(du -s $TMP_DIR/rootfs | awk '{ print 32*int(($1+36000)/32768) "M" }')
2624 cp -a $TMP_DIR/iso $TMP_DIR/rootcd
2625 ISO_SIZE=$(df -h $TMP_DIR/iso | awk 'END { print $2 }')
2626 BUILD_DATE=$(date '+%Y%m%d at %T' -r "$TMP_DIR/iso/md5sum")
2627 umount -d $TMP_DIR/iso
2628 INITRAMFS_SIZE=$(du -chs $TMP_DIR/rootcd/boot/rootfs*.gz | awk 'END { print $1 }')
2629 rm -f $TMP_DIR/rootcd/boot/rootfs.gz $TMP_DIR/rootcd/md5sum
2630 mv $TMP_DIR/rootcd/boot $TMP_DIR/rootfs
2631 [ -d $TMP_DIR/rootcd/efi ] && mv $TMP_DIR/rootcd/efi $TMP_DIR/rootfs
2632 sed 's/.* \(.*\).tazpkg*/\1/' > $TMP_DIR/$FLAVOR.pkglist \
2633 < $TMP_DIR/rootfs$INSTALLED.md5
2634 PKGCNT=$(grep -v ^# $TMP_DIR/$FLAVOR.pkglist | wc -l | awk '{ print $1 }')
2635 if [ -s $TMP_DIR/flavor/*desc ]; then
2636 cp $TMP_DIR/flavor/*.desc $TMP_DIR/$FLAVOR.desc
2637 [ -s $TMP_DIR/$FLAVOR.receipt ] &&
2638 cp $TMP_DIR/flavor/*.receipt $TMP_DIR/$FLAVOR.receipt
2639 for i in rootfs rootcd ; do
2640 [ -s $TMP_DIR/flavor/*.list$i ] &&
2641 sed 's/.\{1,45\}//;/^\.$/d' $TMP_DIR/flavor/*.list$i | \
2642 ( cd $TMP_DIR/$i ; cpio -o -H newc ) | dogzip $TMP_DIR/$FLAVOR.$i
2643 done
2644 else
2645 find_flavor_rootfs $TMP_DIR/rootfs
2646 [ -d $TMP_DIR/rootfs/boot ] && mv $TMP_DIR/rootfs/boot $TMP_DIR/rootcd
2647 [ -d $TMP_DIR/rootfs/efi ] && mv $TMP_DIR/rootfs/efi $TMP_DIR/rootcd
2648 for i in rootfs rootcd ; do
2649 [ "$(ls $TMP_DIR/$i)" ] &&
2650 ( cd "$TMP_DIR/$i"; find * | cpio -o -H newc ) | dogzip "$TMP_DIR/$FLAVOR.$i"
2651 done
2652 unset VERSION MAINTAINER
2653 echo -en "Flavor short description \007: "; read -t 30 DESCRIPTION
2654 if [ -n "$DESCRIPTION" ]; then
2655 _n 'Flavor version : '; read -t 30 VERSION
2656 _n 'Flavor maintainer (your email) : '; read -t 30 MAINTAINER
2657 fi
2659 cat > $TMP_DIR/$FLAVOR.desc <<EOT
2660 Flavor : $FLAVOR
2661 Description : ${DESCRIPTION:-SliTaz $FLAVOR flavor}
2662 Version : ${VERSION:-1.0}
2663 Maintainer : ${MAINTAINER:-nobody@slitaz.org}
2664 LiveCD RAM size : $RAM_SIZE
2665 Build date : $BUILD_DATE
2666 Packages : $PKGCNT
2667 Rootfs size : $ROOTFS_SIZE
2668 Initramfs size : $INITRAMFS_SIZE
2669 ISO image size : $ISO_SIZE
2670 ================================================================================
2672 EOT
2673 longline "Tazlito can't detect each file installed during \
2674 a package post_install. You should extract this flavor (tazlito extract-flavor \
2675 $FLAVOR), check the files in /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/rootfs \
2676 tree and remove files generated by post_installs.
2677 Check /home/slitaz/flavors/$(cat /etc/slitaz-release)/$FLAVOR/receipt too and \
2678 repack the flavor (tazlito pack-flavor $FLAVOR)"
2679 fi
2680 ( cd $TMP_DIR; ls $FLAVOR.* | cpio -o -H newc ) | dogzip $FLAVOR.flavor
2681 fi
2682 fi
2683 rm -rf $TMP_DIR
2684 ;;
2687 gen-distro)
2688 # Generate a live distro tree with a set of packages.
2690 check_root
2691 start_time=$(date +%s)
2693 # Tazlito options: --iso or --cdrom
2694 CDROM=''
2695 [ -n "$iso" ] && CDROM="-o loop $iso"
2696 [ -n "$cdrom" ] && CDROM="/dev/cdrom"
2698 # Check if a package list was specified on cmdline.
2699 if [ -f "$2" ]; then
2700 LIST_NAME="$2"
2701 else
2702 LIST_NAME='distro-packages.list'
2703 fi
2705 [ -d "$ROOTFS" -a -z "$forced" ] && die "A rootfs exists in '$DISTRO'." \
2706 'Please clean the distro tree or change directory path.'
2707 [ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
2708 [ -d "$ROOTCD" ] && rm -rf "$ROOTCD"
2710 # If list not given: build list with all installed packages
2711 if [ ! -f "$LIST_NAME" -a -f "$LOCALSTATE/installed.info" ]; then
2712 awk -F$'\t' '{print $1}' "$LOCALSTATE/installed.info" >> "$LIST_NAME"
2713 fi
2715 # Exit if no list name.
2716 [ ! -f "$LIST_NAME" ] && die 'No packages list found or specified. Please read the docs.'
2718 # Start generation.
2719 title 'Tazlito generating a distro'
2721 # Misc checks
2722 mkdir -p "$PACKAGES_REPOSITORY"
2723 REPACK=$(yesorno 'Repack packages from rootfs?' 'n')
2724 newline
2726 # Mount CD-ROM to be able to repack boot-loader packages
2727 if [ ! -e /boot -a -n "$CDROM" ]; then
2728 mkdir $TMP_MNT
2729 if mount -r "$CDROM $TMP_MNT" 2>/dev/null; then
2730 ln -s "$TMP_MNT/boot" /
2731 if [ ! -d "$ADDFILES/rootcd" ] ; then
2732 mkdir -p "$ADDFILES/rootcd"
2733 for i in $(ls $TMP_MNT); do
2734 [ "$i" = 'boot' ] && continue
2735 cp -a "$TMP_MNT/$i" "$ADDFILES/rootcd"
2736 done
2737 fi
2738 else
2739 rmdir "$TMP_MNT"
2740 fi
2741 fi
2743 # Rootfs stuff.
2744 echo 'Preparing the rootfs directory...'
2745 mkdir -p "$ROOTFS"
2746 export root="$ROOTFS"
2747 # pass current 'mirror' to the root
2748 mkdir -p $root/var/lib/tazpkg $root/etc
2749 cp -f /var/lib/tazpkg/mirror $root/var/lib/tazpkg/mirror
2750 cp -f /etc/slitaz-release $root/etc/slitaz-release
2751 strip_versions "$LIST_NAME"
2753 if [ "$REPACK" = 'y' ]; then
2754 # Determine full packages list with all dependencies
2755 tmp_dir="$(mktemp -d)"
2756 cp "$LIST_NAME" "$tmp_dir/flavor.pkglist"
2757 touch "$tmp_dir/full.pkglist"
2758 module calc_sizes "$tmp_dir" 'flavor' "$tmp_dir/full.pkglist" >/dev/null
2760 awk -F$'\t' '{printf "%s %s\n", $1, $2}' "$LOCALSTATE/installed.info" | \
2761 while read pkgname pkgver; do
2762 # Is package in full list?
2763 grep -q "^$pkgname$" "$tmp_dir/full.pkglist" || continue
2764 # Is package already repacked?
2765 [ -e "$PACKAGES_REPOSITORY/$pkgname-$pkgver.tazpkg" ] && continue
2766 _ 'Repacking %s...' "$pkgname-$pkgver"
2767 tazpkg repack "$pkgname" --quiet
2768 [ -f "$pkgname-$pkgver.tazpkg" ] && mv "$pkgname-$pkgver.tazpkg" "$PACKAGES_REPOSITORY"
2769 status
2770 done
2772 rm -r "$tmp_dir"
2773 fi
2775 if [ -f non-free.list ]; then
2776 # FIXME: working in the ROOTFS chroot?
2777 newline
2778 echo 'Preparing non-free packages...'
2779 cp 'non-free.list' "$ROOTFS/etc/tazlito/non-free.list"
2780 for pkg in $(cat 'non-free.list'); do
2781 if [ ! -d "$INSTALLED/$pkg" ]; then
2782 if [ ! -d "$INSTALLED/get-$pkg" ]; then
2783 tazpkg get-install get-$pkg
2784 fi
2785 get-$pkg "$ROOTFS"
2786 fi
2787 tazpkg repack $pkg
2788 pkg=$(ls $pkg*.tazpkg)
2789 grep -q "^$pkg$" $LIST_NAME || echo $pkg >> $LIST_NAME
2790 mv $pkg $PACKAGES_REPOSITORY
2791 done
2792 fi
2793 cp $LIST_NAME $DISTRO/distro-packages.list
2794 newline
2796 install_list_to_rootfs "$DISTRO/distro-packages.list" "$ROOTFS"
2798 cd $DISTRO
2799 cp distro-packages.list $ROOTFS/etc/tazlito
2800 # Copy all files from $ADDFILES/rootfs to the rootfs.
2801 if [ -d "$ADDFILES/rootfs" ] ; then
2802 action 'Copying addfiles content to the rootfs...'
2803 cp -a $ADDFILES/rootfs/* $ROOTFS
2804 status
2805 fi
2807 action 'Root filesystem is generated...'; status
2809 # Root CD part.
2810 action 'Preparing the rootcd directory...'
2811 mkdir -p $ROOTCD
2812 status
2814 # Move the boot dir with the Linux kernel from rootfs.
2815 # The efi & boot dirs go directly on the CD.
2816 if [ -d "$ROOTFS/efi" ] ; then
2817 action 'Moving the efi directory...'
2818 mv $ROOTFS/efi $ROOTCD
2819 status
2820 fi
2821 if [ -d "$ROOTFS/boot" ] ; then
2822 action 'Moving the boot directory...'
2823 mv $ROOTFS/boot $ROOTCD
2824 status
2825 fi
2826 cd $DISTRO
2827 # Copy all files from $ADDFILES/rootcd to the rootcd.
2828 if [ -d "$ADDFILES/rootcd" ] ; then
2829 action 'Copying addfiles content to the rootcd...'
2830 cp -a $ADDFILES/rootcd/* $ROOTCD
2831 status
2832 fi
2833 # Execute the distro script used to perform tasks in the rootfs
2834 # before compression. Give rootfs path in arg
2835 [ -z "$DISTRO_SCRIPT" ] && DISTRO_SCRIPT="$TOP_DIR/distro.sh"
2836 if [ -x "$DISTRO_SCRIPT" ]; then
2837 echo 'Executing distro script...'
2838 sh $DISTRO_SCRIPT $DISTRO
2839 fi
2841 # Execute the custom_rules() found in receipt.
2842 if [ -s "$TOP_DIR/receipt" ]; then
2843 if grep -q ^custom_rules "$TOP_DIR/receipt"; then
2844 echo -e "Executing: custom_rules()\n"
2845 . "$TOP_DIR/receipt"
2846 custom_rules || echo -e "\nERROR: custom_rules() failed\n"
2847 fi
2848 fi
2850 # Multi-rootfs
2851 if [ -s /etc/tazlito/rootfs.list ]; then
2853 FLAVOR_LIST="$(awk '{
2854 for (i = 2; i <= NF; i+=2)
2855 printf "%s ", $i;
2856 }' /etc/tazlito/rootfs.list)"
2858 [ -s "$ROOTCD/boot/isolinux/isolinux.msg" ] &&
2859 sed -i "s/ *//;s/)/), flavors $FLAVOR_LIST/" \
2860 "$ROOTCD/boot/isolinux/isolinux.msg" 2>/dev/null
2862 [ -f "$ROOTCD/boot/isolinux/ifmem.c32" -o \
2863 -f "$ROOTCD/boot/isolinux/c32box.c32" ] ||
2864 cp '/boot/isolinux/c32box.c32' "$ROOTCD/boot/isolinux" 2>/dev/null ||
2865 cp '/boot/isolinux/ifmem.c32' "$ROOTCD/boot/isolinux"
2867 n=0
2868 last=$ROOTFS
2869 while read flavor; do
2870 n=$(($n+1))
2871 mkdir ${ROOTFS}0$n
2872 export root="${ROOTFS}0$n"
2873 # initial tazpkg setup in empty rootfs
2874 tazpkg --root=$root >/dev/null 2>&1
2876 newline
2877 boldify "Building $flavor rootfs..."
2879 [ -s "$TOP_DIR/$flavor.flavor" ] &&
2880 cp "$TOP_DIR/$flavor.flavor" .
2882 if [ ! -s "$flavor.flavor" ]; then
2883 # We may have it in $FLAVORS_REPOSITORY
2884 if [ -d "$FLAVORS_REPOSITORY/$flavor" ]; then
2885 tazlito pack-flavor $flavor
2886 else
2887 download $flavor.flavor
2888 fi
2889 fi
2891 action 'Extracting %s and %s...' "$flavor.pkglist" "$flavor.rootfs"
2892 zcat $flavor.flavor | cpio -i --quiet $flavor.pkglist $flavor.rootfs
2893 cp $flavor.pkglist $DISTRO/list-packages0$n
2894 status
2896 strip_versions "$DISTRO/list-packages0$n"
2898 install_list_to_rootfs "$DISTRO/list-packages0$n" "${ROOTFS}0$n"
2900 action 'Updating the boot directory...'
2901 yes n | cp -ai ${ROOTFS}0$n/boot $ROOTCD 2> /dev/null
2902 rm -rf ${ROOTFS}0$n/boot
2904 cd $DISTRO
2905 if [ -s $flavor.rootfs ]; then
2906 _n 'Adding %s rootfs extra files...' "$flavor"
2907 zcat < $flavor.rootfs | ( cd ${ROOTFS}0$n ; cpio -idmu )
2908 fi
2910 action 'Moving %s to %s' "list-packages0$n" "rootfs0$n"
2911 mv "$DISTRO/list-packages0$n" "${ROOTFS}0$n/etc/tazlito/distro-packages.list"
2912 status
2914 rm -f $flavor.flavor install-list
2915 mergefs ${ROOTFS}0$n $last
2916 last=${ROOTFS}0$n
2917 done <<EOT
2918 $(awk '{ for (i = 4; i <= NF; i+=2) print $i; }' < /etc/tazlito/rootfs.list)
2919 EOT
2920 #'
2921 i=$(($n+1))
2922 while [ $n -gt 0 ]; do
2923 mv ${ROOTFS}0$n ${ROOTFS}$i
2924 _ 'Compressing %s (%s)...' "${ROOTFS}0$n" "$(du -hs ${ROOTFS}$i | awk '{ print $1 }')"
2925 gen_initramfs ${ROOTFS}$i
2926 n=$(($n-1))
2927 i=$(($i-1))
2928 export LZMA_HISTORY_BITS=26
2929 done
2930 mv $ROOTFS ${ROOTFS}$i
2931 gen_initramfs ${ROOTFS}$i
2932 update_bootconfig "$ROOTCD/boot/isolinux" "$(cat /etc/tazlito/rootfs.list)"
2933 ROOTFS=${ROOTFS}1
2934 else
2935 # Initramfs and ISO image stuff.
2936 gen_initramfs $ROOTFS
2937 fi
2938 gen_livecd_isolinux
2939 distro_stats
2940 cleanup
2941 ;;
2944 clean-distro)
2945 # Remove old distro tree.
2947 check_root
2948 title 'Cleaning: %s' "$DISTRO"
2949 if [ -d "$DISTRO" ] ; then
2950 if [ -d "$ROOTFS" ] ; then
2951 action 'Removing the rootfs...'
2952 rm -f $DISTRO/$INITRAMFS
2953 rm -rf $ROOTFS
2954 status
2955 fi
2956 if [ -d "$ROOTCD" ] ; then
2957 action 'Removing the rootcd...'
2958 rm -rf $ROOTCD
2959 status
2960 fi
2961 action 'Removing eventual ISO image...'
2962 rm -f $DISTRO/$ISO_NAME.iso
2963 rm -f $DISTRO/$ISO_NAME.md5
2964 status
2965 fi
2966 footer
2967 ;;
2970 check-distro)
2971 # Check for a few LiveCD needed files not installed by packages.
2973 # TODO: Remove this function.
2974 # First two files are maintained by tazpkg while it runs on rootfs,
2975 # while last one file should be maintained by tazlito itself.
2976 check_rootfs
2977 title 'Checking distro: %s' "$ROOTFS"
2978 # SliTaz release info.
2979 rel='/etc/slitaz-release'
2980 if [ ! -f "$ROOTFS$rel" ]; then
2981 _ 'Missing release info: %s' "$rel"
2982 else
2983 action 'Release : %s' "$(cat $ROOTFS$rel)"
2984 status
2985 fi
2986 # Tazpkg mirror.
2987 if [ ! -f "$ROOTFS$LOCALSTATE/mirror" ]; then
2988 action 'Mirror URL : Missing %s' "$LOCALSTATE/mirror"
2989 todomsg
2990 else
2991 action 'Mirror configuration exists...'
2992 status
2993 fi
2994 # Isolinux msg
2995 if grep -q "cooking-XXXXXXXX" /$ROOTCD/boot/isolinux/isolinux.*g; then
2996 action 'Isolinux msg : Missing cooking date XXXXXXXX (ex %s)' "$(date +%Y%m%d)"
2997 todomsg
2998 else
2999 action 'Isolinux message seems good...'
3000 status
3001 fi
3002 footer
3003 ;;
3006 writeiso)
3007 # Writefs to ISO image including /home unlike gen-distro we don't use
3008 # packages to generate a rootfs, we build a compressed rootfs with all
3009 # the current filesystem similar to 'tazusb writefs'.
3011 DISTRO='/home/slitaz/distro'
3012 ROOTCD="$DISTRO/rootcd"
3013 COMPRESSION="${2:-none}"
3014 ISO_NAME="${3:-slitaz}"
3015 check_root
3016 # Start info
3017 title 'Write filesystem to ISO'
3018 longline "The command writeiso will write the current filesystem into a \
3019 suitable cpio archive (rootfs.gz) and generate a bootable ISO image (slitaz.iso)."
3020 newline
3021 emsg "<b>Archive compression:</b> <c 36>$COMPRESSION</c>"
3023 [ "$COMPRESSION" = 'gzip' ] && colorize 31 "gzip-compressed rootfs unsupported and may fail to boot"
3024 # Save some space
3025 rm -rf /var/cache/tazpkg/*
3026 rm -f /var/lib/tazpkg/*.bak
3027 rm -rf $DISTRO
3029 # Optionally remove sound card selection and screen resolution.
3030 if [ -z $LaunchedByTazpanel ]; then
3031 anser=$(yesorno 'Do you wish to remove the sound card and screen configs?' 'n')
3032 case $anser in
3033 y)
3034 action 'Removing current sound card and screen configurations...'
3035 rm -f /var/lib/sound-card-driver
3036 rm -f /var/lib/alsa/asound.state
3037 rm -f /etc/X11/xorg.conf ;;
3038 *)
3039 action 'Keeping current sound card and screen configurations...' ;;
3040 esac
3041 status
3042 newline
3044 # Optionally remove i18n settings
3045 anser=$(yesorno 'Do you wish to remove locale/keymap settings?' 'n')
3046 case $anser in
3047 y)
3048 action 'Removing current locale/keymap settings...'
3049 newline > /etc/locale.conf
3050 newline > /etc/keymap.conf ;;
3051 *)
3052 action 'Keeping current locale/keymap settings...' ;;
3053 esac
3054 status
3055 fi
3057 # Clean-up files by default
3058 newline > /etc/udev/rules.d/70-persistent-net.rules
3059 newline > /etc/udev/rules.d/70-persistant-cd.rules
3061 # Create list of files including default user files since it is defined in /etc/passwd
3062 # and some new users might have been added.
3063 cd /
3064 echo 'init' > /tmp/list
3065 for dir in bin etc sbin var dev lib root usr home opt; do
3066 [ -d $dir ] && find $dir
3067 done >> /tmp/list
3069 for dir in proc sys tmp mnt media media/cdrom media/flash media/usbdisk run run/udev; do
3070 [ -d $dir ] && echo $dir
3071 done >> /tmp/list
3073 sed '/var\/run\/.*pid$/d ; /var\/run\/utmp/d ; /.*\/.gvfs/d ; /home\/.*\/.cache\/.*/d' -i /tmp/list
3075 #if [ ! $(find /var/log/slitaz/tazpkg.log -size +4k) = "" ]; then
3076 # sed -i "/var\/log\/slitaz\/tazpkg.log/d" /tmp/list
3077 #fi
3078 mv -f /var/log/wtmp /tmp/tazlito-wtmp
3079 touch /var/log/wtmp
3081 for removelog in auth boot messages dmesg daemon slim .*old Xorg tazpanel cups; do
3082 sed -i "/var\/log\/$removelog/d" /tmp/list
3083 done
3085 # Generate initramfs with specified compression and display rootfs
3086 # size in realtime.
3087 rm -f /tmp/.write-iso* /tmp/rootfs 2>/dev/null
3089 write_initramfs &
3090 sleep 2
3091 cd - > /dev/null
3092 echo -en "\nFilesystem size:"
3093 while [ ! -f /tmp/rootfs ]; do
3094 sleep 1
3095 echo -en "\\033[18G$(du -sh /$INITRAMFS | awk '{print $1}') "
3096 done
3097 mv -f /tmp/tazlito-wtmp /var/log/wtmp
3098 echo -e "\n"
3099 rm -f /tmp/rootfs
3101 # Move freshly generated rootfs to the cdrom.
3102 mkdir -p $ROOTCD/boot
3103 mv -f /$INITRAMFS $ROOTCD/boot
3104 _ 'Located in: %s' "$ROOTCD/boot/$INITRAMFS"
3106 # Now we need the kernel and isolinux files.
3107 copy_from_cd() {
3108 cp /media/cdrom/boot/bzImage* $ROOTCD/boot
3109 cp -a /media/cdrom/boot/isolinux $ROOTCD/boot
3110 unmeta_boot $ROOTCD
3111 umount /media/cdrom
3114 if mount /dev/cdrom /media/cdrom 2>/dev/null; then
3115 copy_from_cd;
3116 elif mount | grep /media/cdrom; then
3117 copy_from_cd;
3118 #elif [ -f "$bootloader" -a -f /boot/vmlinuz*slitaz* ]; then
3119 # [ -f /boot/*slitaz ] && cp /boot/vmlinuz*slitaz $ROOTCD/boot/bzImage
3120 # [ -f /boot/*slitaz64 ] && cp /boot/vmlinuz*slitaz64 $ROOTCD/boot/bzImage64
3121 else
3122 touch /tmp/.write-iso-error
3123 longline "When SliTaz is running in RAM the kernel and bootloader \
3124 files are kept on the CD-ROM. `boldify ' Please insert a Live CD or run:
3125 # mount -o loop slitaz.iso /media/cdrom ' ` to let Tazlito copy the files."
3126 echo -en "----\nENTER to continue..."; read i
3127 [ ! -d /media/cdrom/boot/isolinux ] && exit 1
3128 copy_from_cd
3129 fi
3131 # Generate the iso image.
3132 touch /tmp/.write-iso
3133 newline
3134 cd $DISTRO
3135 create_iso $ISO_NAME.iso $ROOTCD
3136 action 'Creating the ISO md5sum...'
3137 md5sum $ISO_NAME.iso > $ISO_NAME.md5
3138 status
3140 footer "ISO image: $(du -sh $DISTRO/$ISO_NAME.iso)"
3141 rm -f /tmp/.write-iso
3143 if [ -z $LaunchedByTazpanel ]; then
3144 anser=$(yesorno 'Burn ISO to CD-ROM?' 'n')
3145 case $anser in
3146 y)
3147 umount /dev/cdrom 2>/dev/null
3148 eject
3149 echo -n "Please insert a blank CD-ROM and press ENTER..."
3150 read i && sleep 2
3151 tazlito burn-iso $DISTRO/$ISO_NAME.iso
3152 echo -en "----\nENTER to continue..."; read i ;;
3153 *)
3154 exit 0 ;;
3155 esac
3156 fi
3157 ;;
3160 burn-iso)
3161 # Guess CD-ROM device, ask user and burn the ISO.
3163 check_root
3164 DRIVE_NAME=$(grep "drive name" /proc/sys/dev/cdrom/info | cut -f3)
3165 DRIVE_SPEED=$(grep "drive speed" /proc/sys/dev/cdrom/info | cut -f3)
3166 # We can specify an alternative ISO from the cmdline.
3167 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3168 [ ! -f "$iso" ] && die "Unable to find ISO: $iso"
3170 title 'Tazlito burn ISO'
3171 echo "CD-ROM device : /dev/$DRIVE_NAME"
3172 echo "Drive speed : $DRIVE_SPEED"
3173 echo "ISO image : $iso"
3174 footer
3176 case $(yesorno 'Burn ISO image?' 'n') in
3177 y)
3178 title 'Starting Wodim to burn the ISO...'
3179 sleep 2
3180 wodim speed=$DRIVE_SPEED dev=/dev/$DRIVE_NAME $iso
3181 footer 'ISO image is burned to CD-ROM.'
3182 ;;
3183 *)
3184 die 'Exiting. No ISO burned.'
3185 ;;
3186 esac
3187 ;;
3190 merge)
3191 # Merge multiple rootfs into one iso.
3193 if [ -z "$2" ]; then
3194 cat <<EOT
3195 Usage: tazlito merge size1 iso size2 rootfs2 [sizeN rootfsN]...
3197 Merge multiple rootfs into one ISO. Rootfs are like russian dolls
3198 i.e: rootfsN is a subset of rootfsN-1
3199 rootfs1 is found in ISO, sizeN is the RAM size needed to launch rootfsN.
3200 The boot loader will select the rootfs according to the RAM size detected.
3202 Example:
3203 $ tazlito merge 160M slitaz-core.iso 96M rootfs-justx.gz 32M rootfs-base.gz
3205 Will start slitaz-core with 160M+ RAM, slitaz-justX with 96M-160M RAM,
3206 slitaz-base with 32M-96M RAM and display an error message if RAM < 32M.
3208 EOT
3209 exit 2
3210 fi
3212 shift # skip merge
3213 append="$1 slitaz1"
3214 shift # skip size1
3215 mkdir -p $TMP_DIR/mnt $TMP_DIR/rootfs1
3217 ISO=$1.merged
3219 # Extract filesystems
3220 action 'Mounting %s' "$1"
3221 mount -o loop,ro $1 $TMP_DIR/mnt 2> /dev/null
3222 status || cleanup_merge
3224 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3225 make_bzImage_hardlink $TMP_DIR/iso/boot
3226 umount -d $TMP_DIR/mnt
3227 if [ -f $TMP_DIR/iso/boot/rootfs1.gz ]; then
3228 _ '%s is already a merged iso. Aborting.' "$1"
3229 cleanup_merge
3230 fi
3231 if [ ! -f $TMP_DIR/iso/boot/isolinux/ifmem.c32 -a
3232 ! -f $TMP_DIR/iso/boot/isolinux/c32box.c32 ]; then
3233 if [ ! -f /boot/isolinux/ifmem.c32 -a
3234 ! -f /boot/isolinux/c32box.c32 ]; then
3235 cat <<EOT
3236 No file /boot/isolinux/ifmem.c32
3237 Please install syslinux package !
3238 EOT
3239 rm -rf $TMP_DIR
3240 exit 1
3241 fi
3242 cp /boot/isolinux/c32box.c32 $TMP_DIR/iso/boot/isolinux 2> /dev/null ||
3243 cp /boot/isolinux/ifmem.c32 $TMP_DIR/iso/boot/isolinux
3244 fi
3246 action 'Extracting %s' 'iso/rootfs.gz'
3247 extract_rootfs $TMP_DIR/iso/boot/rootfs.gz $TMP_DIR/rootfs1 &&
3248 [ -d $TMP_DIR/rootfs1/etc ]
3249 status || cleanup_merge
3251 n=1
3252 while [ -n "$2" ]; do
3253 shift # skip rootfs N-1
3254 p=$n
3255 n=$(($n + 1))
3256 append="$append $1 slitaz$n"
3257 shift # skip size N
3258 mkdir -p $TMP_DIR/rootfs$n
3260 action 'Extracting %s' "$1"
3261 extract_rootfs $1 $TMP_DIR/rootfs$n &&
3262 [ -d "$TMP_DIR/rootfs$n/etc" ]
3263 status || cleanup_merge
3265 mergefs $TMP_DIR/rootfs$n $TMP_DIR/rootfs$p
3266 action 'Creating %s' "rootfs$p.gz"
3267 pack_rootfs "$TMP_DIR/rootfs$p" "$TMP_DIR/iso/boot/rootfs$p.gz"
3268 status
3269 done
3270 action 'Creating %s' "rootfs$n.gz"
3271 pack_rootfs "$TMP_DIR/rootfs$n" "$TMP_DIR/iso/boot/rootfs$n.gz"
3272 status
3273 rm -f $TMP_DIR/iso/boot/rootfs.gz
3274 update_bootconfig $TMP_DIR/iso/boot/isolinux "$append"
3275 create_iso $ISO $TMP_DIR/iso
3276 rm -rf $TMP_DIR
3277 ;;
3280 repack)
3281 # Repack an iso with maximum lzma compression ratio.
3283 ISO=$2
3284 mkdir -p $TMP_DIR/mnt
3286 # Extract filesystems
3287 action 'Mounting %s' "$ISO"
3288 mount -o loop,ro $ISO $TMP_DIR/mnt 2>/dev/null
3289 status || cleanup_merge
3291 cp -a $TMP_DIR/mnt $TMP_DIR/iso
3292 umount -d $TMP_DIR/mnt
3294 for i in $TMP_DIR/iso/boot/rootfs* ; do
3295 action 'Repacking %s' "$(basename $i)"
3296 uncompress $i 2>/dev/null > $TMP_DIR/rootfs
3297 lzma e $TMP_DIR/rootfs $i $(lzma_switches $TMP_DIR/rootfs)
3298 align_to_32bits $i
3299 status
3300 done
3302 create_iso $ISO $TMP_DIR/iso
3303 rm -rf $TMP_DIR
3304 ;;
3307 build-loram)
3308 # Build a Live CD for low RAM systems.
3310 ISO="$2"
3311 OUTPUT="$3"
3312 [ -z "$3" ] && \
3313 die "Usage: tazlito build-loram <input>.iso <output>.iso [cdrom|smallcdrom|http|ram]"
3314 mkdir -p "$TMP_DIR/iso"
3315 mount -o loop,ro -t iso9660 "$ISO" "$TMP_DIR/iso"
3316 loopdev=$( (losetup -a 2>/dev/null || losetup) | sed "/$(echo $ISO | sed 's|/|\\/|g')$/!d;s/:.*//;q")
3317 if ! check_iso_for_loram ; then
3318 umount -d "$TMP_DIR/iso"
3319 die "$ISO is not a valid SliTaz live CD. Abort."
3320 fi
3321 case "$4" in
3322 cdrom) build_loram_cdrom ;;
3323 http) build_loram_http ;;
3324 *) build_loram_ram "$5" ;;
3325 esac
3326 umount $TMP_DIR/iso # no -d: needs /proc
3327 losetup -d $loopdev
3328 rm -rf $TMP_DIR
3329 ;;
3332 emu-iso)
3333 # Emulate an ISO image with Qemu.
3334 iso="${2:-$DISTRO/$ISO_NAME.iso}"
3335 [ -f "$iso" ] || die "Unable to find ISO file '$iso'."
3336 [ -x '/usr/bin/qemu' ] || die "Unable to find Qemu binary. Please install package 'qemu'."
3337 echo -e "\nStarting Qemu emulator:\n"
3338 echo -e "qemu $QEMU_OPTS $iso\n"
3339 qemu $QEMU_OPTS $iso
3340 ;;
3343 deduplicate)
3344 # Deduplicate files in a tree
3345 shift
3346 deduplicate "$@"
3347 ;;
3350 usage|*)
3351 # Print usage also for all unknown commands.
3352 usage
3353 ;;
3354 esac
3356 exit 0