]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - INSTALL/tool/VentoyWorker.sh
Update ko_KR.json (#2286)
[Ventoy.git] / INSTALL / tool / VentoyWorker.sh
1 #!/bin/sh
2
3 . ./tool/ventoy_lib.sh
4
5 print_usage() {
6
7 echo 'Usage: Ventoy2Disk.sh CMD [ OPTION ] /dev/sdX'
8 echo ' CMD:'
9 echo ' -i install Ventoy to sdX (fails if disk already installed with Ventoy)'
10 echo ' -I force install Ventoy to sdX (no matter if installed or not)'
11 echo ' -u update Ventoy in sdX'
12 echo ' -l list Ventoy information in sdX'
13 echo ''
14 echo ' OPTION: (optional)'
15 echo ' -r SIZE_MB preserve some space at the bottom of the disk (only for install)'
16 echo ' -s/-S enable/disable secure boot support (default is enabled)'
17 echo ' -g use GPT partition style, default is MBR (only for install)'
18 echo ' -L Label of the 1st exfat partition (default is Ventoy)'
19 echo ' -n try non-destructive installation (only for install)'
20 echo ''
21 }
22
23
24 SECUREBOOT="YES"
25 VTNEW_LABEL='Ventoy'
26 RESERVE_SIZE_MB=0
27 while [ -n "$1" ]; do
28 if [ "$1" = "-i" ]; then
29 MODE="install"
30 elif [ "$1" = "-I" ]; then
31 MODE="install"
32 FORCE="Y"
33 elif [ "$1" = "-n" ]; then
34 NONDESTRUCTIVE="Y"
35 elif [ "$1" = "-u" ]; then
36 MODE="update"
37 elif [ "$1" = "-l" ]; then
38 MODE="list"
39 elif [ "$1" = "-s" ]; then
40 SECUREBOOT="YES"
41 elif [ "$1" = "-S" ]; then
42 SECUREBOOT="NO"
43 elif [ "$1" = "-g" ]; then
44 VTGPT="YES"
45 elif [ "$1" = "-L" ]; then
46 shift
47 VTNEW_LABEL=$1
48 elif [ "$1" = "-r" ]; then
49 RESERVE_SPACE="YES"
50 shift
51 RESERVE_SIZE_MB=$1
52 elif [ "$1" = "-V" ] || [ "$1" = "--version" ]; then
53 exit 0
54 elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
55 print_usage
56 exit 0
57 else
58 if ! [ -b "$1" ]; then
59 vterr "$1 is NOT a valid device"
60 print_usage
61 exit 1
62 fi
63 DISK=$1
64 # Resolve symlinks now, will be needed to look up information about the device in
65 # the /sys/ filesystem, for example /sys/class/block/${DISK#/dev/}/start
66 # The main use case is supporting /dev/disk/by-id/ symlinks instead of raw devices
67 if [ -L "$DISK" ]; then
68 DISK=$(readlink -e -n "$DISK")
69 fi
70 fi
71
72 shift
73 done
74
75 if [ -z "$MODE" ]; then
76 print_usage
77 exit 1
78 fi
79
80 if ! [ -b "$DISK" ]; then
81 vterr "Disk $DISK does not exist"
82 exit 1
83 fi
84
85 if [ -e /sys/class/block/${DISK#/dev/}/start ]; then
86 vterr "$DISK is a partition, please use the whole disk."
87 echo "For example:"
88 vterr " sudo sh Ventoy2Disk.sh -i /dev/sdb1 <=== This is wrong"
89 vtinfo " sudo sh Ventoy2Disk.sh -i /dev/sdb <=== This is right"
90 echo ""
91 exit 1
92 fi
93
94 if [ -n "$RESERVE_SPACE" -a "$MODE" = "install" ]; then
95 if echo $RESERVE_SIZE_MB | grep -q '^[0-9][0-9]*$'; then
96 vtdebug "User will reserve $RESERVE_SIZE_MB MB disk space"
97 else
98 vterr "$RESERVE_SIZE_MB is invalid for reserved space"
99 exit 1
100 fi
101 fi
102
103 vtdebug "MODE=$MODE FORCE=$FORCE RESERVE_SPACE=$RESERVE_SPACE RESERVE_SIZE_MB=$RESERVE_SIZE_MB"
104
105 #check tools
106 if check_tool_work_ok; then
107 vtdebug "check tool work ok"
108 else
109 vterr "Some tools can not run on current system. Please check log.txt for details."
110 exit 1
111 fi
112
113 if [ "$MODE" = "list" ]; then
114 version=$(get_disk_ventoy_version $DISK)
115 if [ $? -eq 0 ]; then
116 echo "Ventoy Version in Disk: $version"
117
118 vtPart1Type=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"')
119 if [ "$vtPart1Type" = "EE" ]; then
120 echo "Disk Partition Style : GPT"
121 else
122 echo "Disk Partition Style : MBR"
123 fi
124
125 if check_disk_secure_boot $DISK; then
126 echo "Secure Boot Support : YES"
127 else
128 echo "Secure Boot Support : NO"
129 fi
130 else
131 echo "Ventoy Version: NA"
132 fi
133 echo ""
134 exit 0
135 fi
136
137 #check mountpoint
138 check_umount_disk "$DISK"
139
140 if grep "$DISK" /proc/mounts; then
141 vterr "$DISK is already mounted, please umount it first!"
142 exit 1
143 fi
144
145 #check swap partition
146 if swapon --help 2>&1 | grep -q '^ \-s,'; then
147 if swapon -s | grep -q "^${DISK}[0-9]"; then
148 vterr "$DISK is used as swap, please swapoff it first!"
149 exit 1
150 fi
151 fi
152
153 #check access
154 if dd if="$DISK" of=/dev/null bs=1 count=1 >/dev/null 2>&1; then
155 vtdebug "root permission check ok ..."
156 else
157 vterr "Failed to access $DISK, maybe root privilege is needed!"
158 echo ''
159 exit 1
160 fi
161
162
163 #check tmp_mnt directory
164 if [ -d ./tmp_mnt ]; then
165 vtdebug "There is a tmp_mnt directory, now delete it."
166 umount ./tmp_mnt >/dev/null 2>&1
167 rm -rf ./tmp_mnt
168 if [ -d ./tmp_mnt ]; then
169 vterr "tmp_mnt directory exists, please delete it first."
170 exit 1
171 fi
172 fi
173
174
175 if [ "$MODE" = "install" -a -z "$NONDESTRUCTIVE" ]; then
176 vtdebug "install Ventoy ..."
177
178 if [ -n "$VTGPT" ]; then
179 if parted -v > /dev/null 2>&1; then
180 PARTTOOL='parted'
181 else
182 vterr "parted is not found in the system, Ventoy can't create new partitions without it."
183 vterr "You should install \"GNU parted\" first."
184 exit 1
185 fi
186 else
187 if parted -v > /dev/null 2>&1; then
188 PARTTOOL='parted'
189 elif fdisk -v >/dev/null 2>&1; then
190 PARTTOOL='fdisk'
191 else
192 vterr "Both parted and fdisk are not found in the system, Ventoy can't create new partitions."
193 exit 1
194 fi
195 fi
196
197 if [ "$PARTTOOL" = "parted" ]; then
198 if parted $DISK p | grep -i -q 'sector size.*4096.*4096'; then
199 vterr "Currently Ventoy does not support 4K native device."
200 exit 1
201 fi
202 else
203 if fdisk -l $DISK | grep -i -q 'sector size.*4096.*4096'; then
204 vterr "Currently Ventoy does not support 4K native device."
205 exit 1
206 fi
207 fi
208
209
210 version=$(get_disk_ventoy_version $DISK)
211 if [ $? -eq 0 ]; then
212 if [ -z "$FORCE" ]; then
213 vtwarn "$DISK already contains a Ventoy with version $version"
214 vtwarn "Use -u option to do a safe upgrade operation."
215 vtwarn "OR if you really want to reinstall Ventoy to $DISK, please use -I option."
216 vtwarn ""
217 exit 1
218 fi
219 fi
220
221 disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size)
222 disk_size_gb=$(expr $disk_sector_num / 2097152)
223
224 if [ $disk_sector_num -gt 4294967296 ] && [ -z "$VTGPT" ]; then
225 vterr "$DISK is over 2TB size, MBR will not work on it."
226 exit 1
227 fi
228
229 if [ -n "$RESERVE_SPACE" ]; then
230 sum_size_mb=$(expr $RESERVE_SIZE_MB + $VENTOY_PART_SIZE_MB)
231 reserve_sector_num=$(expr $sum_size_mb \* 2048)
232
233 if [ $disk_sector_num -le $reserve_sector_num ]; then
234 vterr "Can't reserve $RESERVE_SIZE_MB MB space from $DISK"
235 exit 1
236 fi
237 fi
238
239 #Print disk info
240 echo "Disk : $DISK"
241 parted -s $DISK p 2>&1 | grep Model
242 echo "Size : $disk_size_gb GB"
243 if [ -n "$VTGPT" ]; then
244 echo "Style: GPT"
245 else
246 echo "Style: MBR"
247 fi
248 echo ''
249
250 if [ -n "$RESERVE_SPACE" ]; then
251 echo "You will reserve $RESERVE_SIZE_MB MB disk space "
252 fi
253 echo ''
254
255 vtwarn "Attention:"
256 vtwarn "You will install Ventoy to $DISK."
257 vtwarn "All the data on the disk $DISK will be lost!!!"
258 echo ""
259
260 read -p 'Continue? (y/n) ' Answer
261 if [ "$Answer" != "y" ]; then
262 if [ "$Answer" != "Y" ]; then
263 exit 0
264 fi
265 fi
266
267 echo ""
268 vtwarn "All the data on the disk $DISK will be lost!!!"
269 read -p 'Double-check. Continue? (y/n) ' Answer
270 if [ "$Answer" != "y" ]; then
271 if [ "$Answer" != "Y" ]; then
272 exit 0
273 fi
274 fi
275
276 if [ $disk_sector_num -le $VENTOY_SECTOR_NUM ]; then
277 vterr "No enough space in disk $DISK"
278 exit 1
279 fi
280
281 # check and umount
282 check_umount_disk "$DISK"
283
284 if ! dd if=/dev/zero of=$DISK bs=64 count=512 status=none conv=fsync; then
285 vterr "Write data to $DISK failed, please check whether it's in use."
286 exit 1
287 fi
288
289 if [ -n "$VTGPT" ]; then
290 vtdebug "format_ventoy_disk_gpt $RESERVE_SIZE_MB $DISK $PARTTOOL ..."
291 format_ventoy_disk_gpt $RESERVE_SIZE_MB $DISK $PARTTOOL
292 else
293 vtdebug "format_ventoy_disk_mbr $RESERVE_SIZE_MB $DISK $PARTTOOL ..."
294 format_ventoy_disk_mbr $RESERVE_SIZE_MB $DISK $PARTTOOL
295 fi
296
297 # format part1
298
299 # DiskSize > 32GB Cluster Size use 128KB
300 # DiskSize < 32GB Cluster Size use 32KB
301 if [ $disk_size_gb -gt 32 ]; then
302 cluster_sectors=256
303 else
304 cluster_sectors=64
305 fi
306
307 PART1=$(get_disk_part_name $DISK 1)
308 PART2=$(get_disk_part_name $DISK 2)
309
310 #clean part2
311 dd status=none conv=fsync if=/dev/zero of=$DISK bs=512 count=32 seek=$part2_start_sector
312
313 #format part1
314 wait_and_create_part ${PART1} ${PART2}
315 if [ -b ${PART1} ]; then
316 vtinfo "Format partition 1 ${PART1} ..."
317 mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
318 if [ $? -ne 0 ]; then
319 echo "mkexfatfs failed, now retry..."
320 mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
321 if [ $? -ne 0 ]; then
322 echo "######### mkexfatfs failed, exit ########"
323 exit 1
324 fi
325 else
326 echo "mkexfatfs success"
327 fi
328 else
329 vterr "${PART1} NOT exist"
330 fi
331
332 vtinfo "writing data to disk ..."
333 dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=446
334
335 if [ -n "$VTGPT" ]; then
336 echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
337 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
338 echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
339 else
340 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
341 fi
342
343 # check and umount
344 check_umount_disk "$DISK"
345
346 xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start_sector
347
348 #test UUID
349 testUUIDStr=$(vtoy_gen_uuid | hexdump -C)
350 vtdebug "test uuid: $testUUIDStr"
351
352 #disk uuid
353 vtoy_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16
354
355 #disk signature
356 vtoy_gen_uuid | dd status=none conv=fsync of=${DISK} skip=12 seek=440 bs=1 count=4
357
358 vtinfo "sync data ..."
359 sync
360
361 vtinfo "esp partition processing ..."
362
363 if [ "$SECUREBOOT" != "YES" ]; then
364 sleep 2
365 check_umount_disk "$DISK"
366 vtoycli partresize -s $DISK $part2_start_sector
367 fi
368
369 echo ""
370 vtinfo "Install Ventoy to $DISK successfully finished."
371 echo ""
372
373 elif [ "$MODE" = "install" -a -n "$NONDESTRUCTIVE" ]; then
374 vtdebug "non-destructive install Ventoy ..."
375
376 version=$(get_disk_ventoy_version $DISK)
377 if [ $? -eq 0 ]; then
378 if [ -z "$FORCE" ]; then
379 vtwarn "$DISK already contains a Ventoy with version $version."
380 vtwarn "You can not do and don not need non-destructive installation."
381 vtwarn ""
382 exit 1
383 fi
384 fi
385
386 disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size)
387 disk_size_gb=$(expr $disk_sector_num / 2097152)
388
389 if vtoycli partresize -t $DISK; then
390 OldStyle="GPT"
391 else
392 OldStyle="MBR"
393 fi
394
395 #Print disk info
396 echo "Disk : $DISK"
397 parted -s $DISK p 2>&1 | grep Model
398 echo "Size : $disk_size_gb GB"
399 echo "Style: $OldStyle"
400 echo ''
401
402 vtwarn "Attention:"
403 vtwarn "Ventoy will try non-destructive installation on $DISK if possible."
404 echo ""
405
406 read -p 'Continue? (y/n) ' Answer
407 if [ "$Answer" != "y" ]; then
408 if [ "$Answer" != "Y" ]; then
409 exit 0
410 fi
411 fi
412
413 if [ $disk_sector_num -le $VENTOY_SECTOR_NUM ]; then
414 vterr "No enough space in disk $DISK"
415 exit 1
416 fi
417
418 PART1=$(get_disk_part_name $DISK 1)
419 PART2=$(get_disk_part_name $DISK 2)
420
421 #Part1 size in MB aligned with 4KB
422 PART1_SECTORS=$(cat /sys/class/block/${PART1#/dev/}/size)
423 PART1_4K=$(expr $PART1_SECTORS / 8)
424 PART1_MB=$(expr $PART1_4K / 256)
425 PART1_NEW_MB=$(expr $PART1_MB - 32)
426
427 echo "$PART1 is ${PART1_MB}MB"
428
429 #check partition layout
430 echo "check partition layout ..."
431 vtoycli partresize -c $DISK
432 vtRet=$?
433 if [ $vtRet -eq 0 ]; then
434 exit 1
435 else
436 # check and umount
437 check_umount_disk "$DISK"
438 sleep 1
439 check_umount_disk "$DISK"
440
441 if [ $vtRet -eq 1 ]; then
442 echo "Free space enough, start install..."
443 part2_start_sector=$(expr $PART1_SECTORS + 2048)
444 elif [ $vtRet -eq 2 ]; then
445 echo "We need to shrink partition 1 firstly ..."
446
447 PART1_BLKID=$(blkid $PART1)
448 blkid $PART1
449
450 if echo $PART1_BLKID | grep -E -q -i 'TYPE=ntfs|TYPE=.ntfs'; then
451 echo "Partition 1 contains NTFS filesystem"
452
453 which ntfsresize
454 if [ $? -ne 0 ]; then
455 echo "###[FAIL] ntfsresize not found. Please install ntfs-3g package."
456 exit 1
457 fi
458
459 echo "ntfsfix -b -d $PART1 ..."
460 ntfsfix -b -d $PART1
461
462 echo "ntfsresize --size ${PART1_NEW_MB}Mi $PART1 ..."
463 ntfsresize -f --size ${PART1_NEW_MB}Mi $PART1
464 if [ $? -ne 0 ]; then
465 echo "###[FAIL] ntfsresize failed."
466 exit 1
467 fi
468 elif echo $PART1_BLKID | grep -E -q -i 'TYPE=ext[2-4]|TYPE=.ext[2-4]'; then
469 echo "Partition 1 contains EXT filesystem"
470
471 which resize2fs
472 if [ $? -ne 0 ]; then
473 echo "###[FAIL] resize2fs not found. Please install e2fsprogs package."
474 exit 1
475 fi
476
477 echo "e2fsck -f $PART1 ..."
478 e2fsck -f $PART1
479
480 echo "resize2fs $PART1 ${PART1_NEW_MB}M ..."
481 resize2fs $PART1 ${PART1_NEW_MB}M
482 if [ $? -ne 0 ]; then
483 echo "###[FAIL] resize2fs failed."
484 exit 1
485 fi
486 else
487 echo "###[FAIL] Unsupported filesystem in partition 1."
488 exit 1
489 fi
490
491 sync
492 PART1_NEW_END_MB=$(expr $PART1_NEW_MB + 1)
493 part2_start_sector=$(expr $PART1_NEW_END_MB \* 2048)
494 fi
495 fi
496
497 vtinfo "writing data to disk part2_start=$part2_start_sector ..."
498
499 dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
500
501 if [ "$OldStyle" = "GPT" ]; then
502 echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
503 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
504 echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
505 else
506 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
507 fi
508
509 xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start_sector
510
511 #test UUID
512 testUUIDStr=$(vtoy_gen_uuid | hexdump -C)
513 vtdebug "test uuid: $testUUIDStr"
514
515 #disk uuid
516 vtoy_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16
517
518 vtinfo "sync data ..."
519 sync
520
521 vtinfo "esp partition processing ..."
522 if [ "$SECUREBOOT" != "YES" ]; then
523 vtoycli partresize -s $DISK $part2_start_sector
524 fi
525
526 vtinfo "update partition table $DISK $part2_start_sector ..."
527 vtoycli partresize -p $DISK $part2_start_sector
528 if [ $? -eq 0 ]; then
529 sync
530 echo ""
531 vtinfo "Ventoy non-destructive installation on $DISK successfully finished."
532 echo ""
533 else
534 echo ""
535 vterr "Ventoy non-destructive installation on $DISK failed."
536 echo ""
537 fi
538
539 else
540 vtdebug "update Ventoy ..."
541
542 oldver=$(get_disk_ventoy_version $DISK)
543 if [ $? -ne 0 ]; then
544 if is_disk_contains_ventoy $DISK; then
545 oldver="Unknown"
546 else
547 vtwarn "$DISK does not contain Ventoy or data corrupted"
548 echo ""
549 vtwarn "Please use -i option if you want to install ventoy to $DISK"
550 echo ""
551 exit 1
552 fi
553 fi
554
555 #reserve secure boot option
556 if [ -z "$SECUREBOOT" ]; then
557 if check_disk_secure_boot $DISK; then
558 SECUREBOOT="YES"
559 else
560 SECUREBOOT="NO"
561 fi
562 fi
563
564 curver=$(cat ./ventoy/version)
565
566 vtinfo "Upgrade operation is safe, all the data in the 1st partition (iso files and other) will be unchanged!"
567 echo ""
568
569 read -p "Update Ventoy $oldver ===> $curver Continue? (y/n) " Answer
570 if [ "$Answer" != "y" ]; then
571 if [ "$Answer" != "Y" ]; then
572 exit 0
573 fi
574 fi
575
576 PART2=$(get_disk_part_name $DISK 2)
577 SHORT_PART2=${PART2#/dev/}
578 part2_start=$(cat /sys/class/block/$SHORT_PART2/start)
579
580 PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"')
581
582 #reserve disk uuid
583 rm -f ./diskuuid.bin
584 dd status=none conv=fsync if=${DISK} skip=384 bs=1 count=16 of=./diskuuid.bin
585
586 dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
587 dd status=none conv=fsync if=./diskuuid.bin of=$DISK bs=1 count=16 seek=384
588 rm -f ./diskuuid.bin
589
590 #reserve data
591 rm -f ./rsvdata.bin
592 dd status=none conv=fsync if=${DISK} skip=2040 bs=512 count=8 of=./rsvdata.bin
593
594 if [ "$PART1_TYPE" = "EE" ]; then
595 vtdebug "This is GPT partition style ..."
596 echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
597 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
598 echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
599 else
600 vtdebug "This is MBR partition style ..."
601
602 PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | hexdump -n1 -e '1/1 "%02X"')
603 PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | hexdump -n1 -e '1/1 "%02X"')
604
605 vtdebug "PART1_ACTIVE=$PART1_ACTIVE PART2_ACTIVE=$PART2_ACTIVE"
606 if [ "$PART1_ACTIVE" = "00" ] && [ "$PART2_ACTIVE" = "80" ]; then
607 vtdebug "change 1st partition active, 2nd partition inactive ..."
608 echo -en '\x80' | dd of=$DISK conv=fsync bs=1 count=1 seek=446 status=none
609 echo -en '\x00' | dd of=$DISK conv=fsync bs=1 count=1 seek=462 status=none
610 fi
611 xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
612 fi
613
614 dd status=none conv=fsync if=./rsvdata.bin seek=2040 bs=512 count=8 of=${DISK}
615 rm -f ./rsvdata.bin
616
617 check_umount_disk "$DISK"
618
619 xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start
620 sync
621
622 vtinfo "esp partition processing ..."
623 if [ "$SECUREBOOT" != "YES" ]; then
624 sleep 2
625 check_umount_disk "$DISK"
626 vtoycli partresize -s $DISK $part2_start
627 fi
628
629 echo ""
630 vtinfo "Update Ventoy on $DISK successfully finished."
631 echo ""
632
633 fi
634
635