You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1117 lines
28 KiB

  1. #!/usr/bin/env bash
  2. version="refractasnapshot-10.2.10 (20191218)"
  3. TEXTDOMAIN=refractasnapshot-base
  4. TEXTDOMAINDIR=/usr/share/locale/
  5. # Copyright: fsmithred@gmail.com 2011-2019
  6. # based on refractasnapshot-8.0.4 by Dean Linkous with ideas
  7. # borrowed from dzsnapshot-gui.sh by David Hare, which was based on an
  8. # earlier version of this script.
  9. # UEFI code adapted from similar scripts by Colin Watson and Patrick J. Volkerding
  10. # License: GPL-3
  11. # This is free software with NO WARRANTY. Use at your own risk!
  12. # DESCRIPTION
  13. # This script makes a copy of your system with rsync and then creates
  14. # an iso file to be used as a live-cd. There are options in the config
  15. # file to change the location of the copy and the location of the final
  16. # iso file, in case there's not enough room on the system drive. Read
  17. # the config file for more options. (/etc/refractasnapshot.conf)
  18. # If you want to change any defaults, change them in the configfile.
  19. # Default is /etc/refractasnapshot.conf
  20. # If you want to use a different config file for testing,
  21. # either change this variable here or use the -c, --config option on
  22. # the command-line. (Command-line option will supercede this setting.)
  23. # Normally, users should not edit anything in this script.
  24. configfile="/etc/refractasnapshot.conf"
  25. show_help () {
  26. printf "$help_text"
  27. exit 0
  28. }
  29. help_text=$"
  30. Usage: $0 [option]
  31. Run with no options to create .iso file for a live, bootable CD
  32. or DVD copy of the running system.
  33. valid options:
  34. -h, --help show this help text
  35. -v, --version display the version information
  36. -d. --debug debug mode
  37. -c, --config specify a different config file
  38. (file name must be next argument)
  39. example:
  40. refractasnapshot -n -c myconfigs
  41. *** See $configfile for information about settings.
  42. "
  43. while [[ $1 == -* ]]; do
  44. case "$1" in
  45. -h|--help)
  46. show_help ;;
  47. -v|--version)
  48. printf "\n$version\n\n"
  49. exit 0 ;;
  50. -c|--config)
  51. shift
  52. configfile="$1"
  53. printf "\n config file is $configfile\n\n"
  54. shift
  55. ;;
  56. -d|--debug)
  57. DEBUG="yes"
  58. shift ;;
  59. *)
  60. printf "\t invalid option: $1 \n\n"
  61. printf "\t Try: $0 -h for full help. \n\n"
  62. exit 1 ;;
  63. esac
  64. done
  65. # Check that user is root.
  66. [[ $(id -u) -eq 0 ]] || { echo -e "\n\t You need to be root!\n" ; exit 1 ; }
  67. [[ -e "$configfile" ]] || { echo "Configuration file, $configfile is missing." ; exit 1 ; }
  68. # Fix root's path (for Buster/Beowulf and later)
  69. PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  70. source "$configfile"
  71. # Record errors in a logfile.
  72. exec 2>"$error_log"
  73. if [[ $DEBUG = "yes" ]] ; then
  74. set -x
  75. fi
  76. echo "configfile is $configfile"
  77. echo "make_efi is $make_efi"
  78. # Check for grub-efi.
  79. check_grub () {
  80. if [[ $make_efi = "yes" ]] ; then
  81. if ! (dpkg -l | grep "^ii" | grep "grub-efi-amd64" |grep -v "bin"); then
  82. echo $"grub-efi-amd64 is not installed"
  83. grub_message=$"Warning: grub-efi-amd64 is not installed. The snapshot may not be compatible with UEFI.
  84. To disable this warning, set make_efi=no in $configfile or set force_efi=yes for special use.
  85. "
  86. if [[ $force_efi = "yes" ]] ; then
  87. make_efi="yes"
  88. else
  89. make_efi="no"
  90. fi
  91. echo "force_efi is $force_efi"
  92. echo "make_efi is $make_efi"
  93. fi
  94. if [[ ! -e /var/lib/dpkg/info/dosfstools.list ]] ; then
  95. echo $"dosfstools is not installed"
  96. dosfstools_message=$"Warning: dosfstools is not installed. Your snapshot will not boot in uefi mode."
  97. force_efi="no"
  98. make_efi="no"
  99. echo "force_efi is $force_efi"
  100. echo "make_efi is $make_efi"
  101. fi
  102. fi
  103. }
  104. show_snapshot_help () {
  105. zless "$snapshot_help"
  106. choose_task
  107. }
  108. find_text_editor () {
  109. # Default text editor is nano. Make sure it exists if user intends to ### This needs attention!!! <<<<<<<<<
  110. # edit files before squashing the filesystem.
  111. #if [[ $edit_boot_menu = "yes" ]] ; then
  112. [[ -e $text_editor ]] || { echo -e $"\n Error! The text editor is set to ${text_editor},
  113. but it is not installed. Edit $configfile
  114. and set the text_editor variable to the editor of your choice.
  115. (examples: /usr/bin/vim, /usr/bin/joe)\n" ; exit 1 ; }
  116. #fi
  117. }
  118. unpatch_init () {
  119. # Check for previous patch.
  120. if $(grep -q nuke "$target_file") ; then
  121. echo $"
  122. It looks like $target_file was previously patched by an
  123. earlier version of refractasnapshot. This patch is no longer needed.
  124. You can comment out the added lines as shown below (or remove the
  125. commented lines) and then run 'update-initramfs -u'.
  126. If you don't want to do that, dont worry;
  127. it won't hurt anything if you leave it the way it is.
  128. Do not change or remove the lines that begin with \"mount\"
  129. mount -n -o move /sys ${rootmnt}/sys
  130. #nuke /sys
  131. #ln -s ${rootmnt}/sys /sys
  132. mount -n -o move /proc ${rootmnt}/proc
  133. #nuke /proc
  134. #ln -s ${rootmnt}/proc /proc
  135. "
  136. while true ; do
  137. echo $"Open $target_file in an editor? (y/N)"
  138. read ans
  139. case $ans in
  140. [Yy]*) "$text_editor" "$target_file"
  141. update-initramfs -u
  142. break ;;
  143. *) break ;;
  144. esac
  145. done
  146. echo -e $"\n Wait for the disk report to complete...\n\n"
  147. fi
  148. }
  149. check_copies () {
  150. # Function to check for old snapshots and filesystem copy and their total size
  151. if [[ -d $snapshot_dir ]]; then
  152. if ls "$snapshot_dir"/*.iso > /dev/null ; then
  153. snapshot_count=$(ls "$snapshot_dir"/*.iso | wc -l)
  154. else
  155. snapshot_count="0"
  156. fi
  157. snapshot_size=$(du -sh "$snapshot_dir" | awk '{print $1}')
  158. if [[ -z $snapshot_size ]]; then
  159. snapshot_size="0 bytes"
  160. fi
  161. else
  162. snapshot_count="0"
  163. snapshot_size="0 bytes"
  164. fi
  165. # Check for saved copy of the system
  166. if [[ -d "$work_dir"/myfs ]]; then
  167. saved_size=$(du -sh "$work_dir"/myfs | awk '{ print $1 }')
  168. saved_copy=$(echo $"* You have a saved copy of the system using $saved_size of space
  169. located at $work_dir/myfs.")
  170. fi
  171. # Create a message to say whether the filesystem copy will be saved or not.
  172. if [[ $save_work = "yes" ]]; then
  173. save_message=$(echo $"* The temporary copy of the filesystem will be saved
  174. at $work_dir/myfs.")
  175. else
  176. save_message=$(echo $"* The temporary copy of the filesystem will be created
  177. at $work_dir/myfs and removed when this program finishes.")
  178. fi
  179. }
  180. check_directories () {
  181. # Create snapshot_dir and work_dir if necessary.
  182. # Don't use /media/* for $snapshot_dir or $work_dir unless it is a mounted filesystem
  183. snapdir_is_remote=$(echo ${snapshot_dir} | awk -F / '{ print "/" $2 "/" $3 }' | grep /media/)
  184. workdir_is_remote=$(echo ${work_dir} | awk -F / '{ print "/" $2 "/" $3 }' | grep /media/)
  185. if [ -n "$snapdir_is_remote" ] && cat /proc/mounts | grep -q ${snapdir_is_remote}; then
  186. echo "$snapshot_dir is mounted"
  187. elif [ -n "$snapdir_is_remote" ] ; then
  188. echo $" Error.. The selected snapshot directory cannot be accessed. Do you need to mount it?"
  189. exit 1
  190. fi
  191. if [ -n "$workdir_is_remote" ] && cat /proc/mounts | grep -q ${workdir_is_remote}; then
  192. echo "$work_dir is mounted"
  193. elif [ -n "$workdir_is_remote" ] ; then
  194. echo $" Error.. The selected work directory cannot be accessed. Do you need to mount it?"
  195. exit 1
  196. fi
  197. # Check that snapshot_dir exists
  198. if ! [[ -d $snapshot_dir ]]; then
  199. mkdir -p "$snapshot_dir"
  200. chmod 777 "$snapshot_dir"
  201. fi
  202. # Check that work directories exist or create them.
  203. if [[ $save_work = "no" ]]; then
  204. if [[ -d $work_dir ]]; then
  205. rm -rf "$work_dir"
  206. fi
  207. mkdir -p "$work_dir"/iso
  208. mkdir -p "$work_dir"/myfs
  209. elif [[ $save_work = "yes" ]]; then
  210. if ! [[ -d $work_dir ]]; then
  211. mkdir -p "$work_dir"/iso
  212. mkdir -p "$work_dir"/myfs
  213. fi
  214. fi
  215. }
  216. check_space () {
  217. # Check disk space on mounted /, /home, /media, /mnt, /tmp
  218. disk_space=$(df -h -x tmpfs -x devtmpfs -x iso9660 | awk '{ print " " $2 "\t" $3 "\t" $4 "\t" $5 " \t" $6 "\t\t\t" $1 }')
  219. }
  220. # Check initrd for cryptroot, resume, cryptsetup.
  221. check_initrd () {
  222. if lsinitramfs "$initrd_image" | grep -q conf.d/cryptroot ; then
  223. remove_cryptroot="yes"
  224. cryptroot_message="The snapshot initrd will be modified to allow booting the unencrypted snapshot."
  225. elif lsinitramfs "$initrd_image" | grep -q cryptroot/crypttab ; then
  226. remove_cryptroot="yes"
  227. cryptroot_message="The snapshot initrd will be modified to allow booting the unencrypted snapshot."
  228. fi
  229. if lsinitramfs "$initrd_image" | egrep -q 'conf.d/resume|conf.d/zz-resume-auto' ; then
  230. remove_resume="yes"
  231. swap_message="The snapshot initrd will be modified to allow booting without the host's swap partition."
  232. fi
  233. if [ "$initrd_crypt" = yes ] ; then
  234. if lsinitramfs "$initrd_image" | grep -q cryptsetup ; then
  235. crypt_message="The host initrd already allows live-usb encrypted persistence. No change is needed."
  236. initrd_crypt="no"
  237. else
  238. crypt_message="The host initrd will be modified to allow live-usb encrypted persistence.
  239. A backup copy will be made at ${initrd_image}_pre-snapshot. (Does not apply to any re-run tasks.)"
  240. fi
  241. fi
  242. }
  243. extract_initrd () {
  244. mkdir /tmp/extracted
  245. pushd /tmp/extracted
  246. COMPRESSION=$(file -L "$initrd_image" | egrep -o 'gzip compressed|XZ compressed|cpio archive')
  247. if [ "$COMPRESSION" = "gzip compressed" ]; then
  248. echo "Archive is gzip compressed..."
  249. zcat "$initrd_image" | cpio -i
  250. elif [ "$COMPRESSION" = "XZ compressed" ]; then
  251. echo "Archive is XZ compressed..."
  252. xzcat "$initrd_image" | cpio -d -i -m
  253. elif [ "$COMPRESSION" = "cpio archive" ]; then
  254. echo "Archive is cpio archive..."
  255. (cpio -i ; zcat | cpio -i) < "$initrd_image"
  256. exit_code="$?"
  257. if [ "$exit_code" -ne 0 ] ; then
  258. (cpio -i ; xzcat | cpio -i) < "$initrd_image"
  259. exit_code="$?"
  260. if [ "$exit_code" -ne 0 ] ; then
  261. echo "Decompression error" && exit 1
  262. else
  263. COMPRESSION="XZ compressed"
  264. fi
  265. else
  266. COMPRESSION="gzip compressed"
  267. fi
  268. echo "COMPRESSION is $COMPRESSION"
  269. else
  270. echo "Decompession error..." && exit 1
  271. fi
  272. popd
  273. echo "Initrd is extracted"
  274. }
  275. edit_initrd () {
  276. pushd /tmp/extracted
  277. if [ -f conf/conf.d/cryptroot ] ; then
  278. echo "Removing cryptroot"
  279. rm -f conf/conf.d/cryptroot
  280. elif [ -f cryptroot/crypttab ] ; then
  281. echo "Removing crypttab"
  282. rm -f cryptroot/crypttab
  283. fi
  284. if [ -f conf/conf.d/resume ] ; then
  285. echo "Removing resume"
  286. rm -f conf/conf.d/resume
  287. rm -f "$work_dir"/myfs/etc/initramfs-tools/conf.d/resume
  288. elif [ -f conf/conf.d/zz-resume-auto ] ; then
  289. echo "Removing resume"
  290. rm -f conf/conf.d/zz-resume-auto
  291. rm -f "$work_dir"/myfs/etc/initramfs-tools/conf.d/resume
  292. fi
  293. popd
  294. }
  295. rebuild_initrd () {
  296. pushd /tmp/extracted
  297. if [ "$COMPRESSION" = "gzip compressed" ] ; then
  298. find . -print0 | cpio -0 -H newc -o | gzip -c > ${work_dir}/iso/live/${initrd_image##*/}
  299. elif [ "$COMPRESSION" = "XZ compressed" ] ; then
  300. find . | cpio -o -H newc | xz --check=crc32 --x86 --lzma2=dict=512KiB > ${work_dir}/iso/live/${initrd_image##*/}
  301. else
  302. echo "Compression error..."
  303. exit 1
  304. fi
  305. popd
  306. rm -rf /tmp/extracted
  307. }
  308. clean_initrd () {
  309. extract_initrd
  310. edit_initrd
  311. rebuild_initrd
  312. }
  313. report_space () {
  314. # Show current settings and disk space
  315. if [[ -f "/usr/bin/less" ]] ; then
  316. pager="/usr/bin/less"
  317. else
  318. pager="/bin/more"
  319. fi
  320. echo $"
  321. You will need plenty of free space. It is recommended that free space
  322. (Avail) in the partition that holds the work directory (probably \"/\")
  323. should be two times the total installed system size (Used). You can
  324. deduct the space taken up by previous snapshots and any saved copies of
  325. the system from the Used amount.
  326. ${grub_message}
  327. ${dosfstools_message}
  328. * You have $snapshot_count snapshots taking up $snapshot_size of disk space.
  329. $saved_copy
  330. $save_message
  331. * The snapshot directory is currently set to $snapshot_dir
  332. $tmp_warning
  333. You can change these and other settings by editing
  334. $configfile.
  335. Turn off NUM LOCK for some laptops.
  336. ${crypt_message}
  337. ${cryptroot_message}
  338. ${swap_message}
  339. Current disk usage:
  340. (For complete listing, exit and run 'df -h')
  341. $disk_space
  342. To proceed, press q.
  343. To exit, press q and then press ctrl-c
  344. " | "$pager"
  345. }
  346. choose_task () {
  347. if [[ $make_efi = "yes" ]] ; then
  348. uefi_message=$"uefi enabled"
  349. else
  350. uefi_message=$"uefi disabled"
  351. fi
  352. while true; do
  353. echo $"
  354. Choose a task.
  355. 1. Create a snapshot ($uefi_message)
  356. 2. Re-squash and make iso (no-copy)
  357. 3. Re-make efi files and iso (no-copy, no-squash)
  358. 4. Re-run xorriso only. (make iso, no-copy, no-squash)
  359. 5. Help
  360. 6. Exit
  361. "
  362. read ans
  363. case $ans in
  364. 1) # Create snapshot
  365. echo $"This may take a moment while the program checks for free space. "
  366. check_copies
  367. check_directories
  368. check_space
  369. check_initrd
  370. report_space
  371. set_distro_name
  372. housekeeping
  373. if [[ $initrd_crypt = "yes" ]] ; then
  374. prepare_initrd_crypt
  375. fi
  376. # The real work starts here 01
  377. cd "$work_dir"
  378. copy_isolinux
  379. copy_kernel
  380. copy_filesystem
  381. if [ "$remove_cryptroot" = yes ] || [ "$remove_resume" = yes ] ; then
  382. clean_initrd
  383. fi
  384. edit_system
  385. get_filename
  386. if [[ $make_efi = "yes" ]] ; then
  387. mkefi
  388. fi
  389. add_extras
  390. set_boot_options
  391. if [[ $edit_boot_menu = "yes" ]] ; then
  392. edit_boot_menus
  393. fi
  394. squash_filesystem
  395. make_iso_fs
  396. cleanup
  397. final_message
  398. exit 0 ;;
  399. 2) # Re-squash
  400. if [[ $make_efi = "yes" ]] ; then
  401. uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
  402. fi
  403. # The real work starts here 02
  404. cd "$work_dir"
  405. get_filename
  406. squash_filesystem
  407. make_iso_fs
  408. final_message
  409. exit 0 ;;
  410. 3) # Re-make efi
  411. # The real work starts here 03
  412. [[ $make_efi = "yes" ]] || exit 1
  413. cd "$work_dir"
  414. get_filename
  415. set_distro_name
  416. mkefi
  417. set_boot_options
  418. find_editor
  419. edit_boot_menus
  420. make_iso_fs
  421. final_message
  422. exit 0 ;;
  423. 4) # Re-make iso
  424. # The real work starts here 04
  425. if [[ $make_efi = "yes" ]] ; then
  426. uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
  427. fi
  428. cd "$work_dir"
  429. get_filename
  430. make_iso_fs
  431. final_message
  432. exit 0 ;;
  433. 5) show_snapshot_help ;;
  434. [6qQxX]) exit 0 ;;
  435. esac
  436. done
  437. }
  438. set_distro_name () {
  439. if [[ $iso_dir = "/usr/lib/refractasnapshot/iso" ]] && [[ $boot_menu = "live.cfg" ]] ; then
  440. DISTRO=$(lsb_release -i -s 2>/dev/null)
  441. if $(grep -q Refracta /etc/issue) ; then
  442. DISTRO="Refracta"
  443. fi
  444. while true ; do
  445. echo $"
  446. This is the distribution name that will appear in the boot menu for the
  447. live image. You can change it to something else, or you can blank this,
  448. and the the menu entries will just say \"GNU/Linux <kernel-version>\"
  449. "
  450. # # Redirect stderr from the error log to the screen,
  451. # # so we can see the prompts from read.
  452. exec 2>&1
  453. read -p $" Enter, erase or change distro name: " -i "$DISTRO" -e answer
  454. # # Resume logging errors.
  455. exec 2>>"$error_log"
  456. break
  457. done
  458. if [[ -z "$answer" ]] ; then
  459. DISTRO="GNU/Linux `uname -r`"
  460. else
  461. DISTRO="$answer"
  462. fi
  463. fi
  464. }
  465. housekeeping () {
  466. # Test for systemd, util-linux version and patch intramfs-tools/init.
  467. if [[ $patch_init_nosystemd = "yes" ]] ; then
  468. utillinux_version=$(dpkg -l util-linux | awk '/util-linux/ { print $3 }' | cut -d. -f2)
  469. target_file="/usr/share/initramfs-tools/init"
  470. # patch_file="/usr/lib/refractasnapshot/init_for_util-lin.patch"
  471. if [[ ! -h /sbin/init ]] ; then
  472. if [[ $utillinux_version -ge 25 ]] ; then
  473. unpatch_init
  474. fi
  475. fi
  476. fi
  477. # Use the login name set in the config file. If not set, use the primary
  478. # user's name. If the name is not "user" then add boot option. ALso use
  479. # the same username for cleaning geany history.
  480. if [[ -n "$username" ]] ; then
  481. username_opt="username=$username"
  482. else
  483. username=$(awk -F":" '/1000:1000/ { print $1 }' /etc/passwd)
  484. if [[ $username != user ]] ; then
  485. username_opt="username=$username"
  486. fi
  487. fi
  488. # Check that kernel and initrd exist
  489. [[ -e "$kernel_image" ]] || kernel_message=" Warning: Kernel image is missing. "
  490. [[ -e "$initrd_image" ]] || initrd_message=" Warning: initrd image is missing. "
  491. if [[ -n "$kernel_message" ]] || [[ -n "$initrd_message" ]] ; then
  492. echo $"
  493. $kernel_message
  494. $initrd_message
  495. Make sure the kernel_image and/or initrd_image
  496. set in the config file are correct, and check
  497. that the boot menu is also correct.
  498. "
  499. exit 1
  500. fi
  501. # update the mlocate database
  502. if [[ $update_mlocate = "yes" ]]; then
  503. echo -e $"\nRunning updatedb...\n"
  504. updatedb
  505. fi
  506. }
  507. prepare_initrd_crypt () {
  508. # Prepare initrd to use encryption
  509. # This is only going to work if the latest kernel version is running.
  510. # (i.e. the one linked from /initrd.img)
  511. # Add '-k all' or specify the initrd to use???
  512. cp "$initrd_image" "${initrd_image}_pre-snapshot"
  513. sed -i 's/.*CRYPTSETUP=.*/CRYPTSETUP=y/' /etc/cryptsetup-initramfs/conf-hook
  514. if [[ -f /usr/sbin/update-initramfs.orig.initramfs-tools ]] ; then
  515. /usr/sbin/update-initramfs.orig.initramfs-tools -u
  516. else
  517. /usr/sbin/update-initramfs -u
  518. fi
  519. }
  520. copy_isolinux () {
  521. if [[ -f /usr/lib/ISOLINUX/isolinux.bin ]] ; then
  522. isolinuxbin="/usr/lib/ISOLINUX/isolinux.bin"
  523. elif [[ -f /usr/lib/syslinux/isolinux.bin ]] ; then
  524. isolinuxbin="/usr/lib/syslinux/isolinux.bin"
  525. else
  526. echo $"You need to install the isolinux package."
  527. exit 1
  528. fi
  529. # @@@@ Warning: This will replace these files in custom iso_dir @@@@@
  530. if [[ -f /usr/lib/syslinux/modules/bios/vesamenu.c32 ]] ; then
  531. vesamenu="/usr/lib/syslinux/modules/bios/vesamenu.c32"
  532. rsync -a /usr/lib/syslinux/modules/bios/chain.c32 "$iso_dir"/isolinux/
  533. rsync -a /usr/lib/syslinux/modules/bios/ldlinux.c32 "$iso_dir"/isolinux/
  534. rsync -a /usr/lib/syslinux/modules/bios/libcom32.c32 "$iso_dir"/isolinux/
  535. rsync -a /usr/lib/syslinux/modules/bios/libutil.c32 "$iso_dir"/isolinux/
  536. else
  537. vesamenu="/usr/lib/syslinux/vesamenu.c32"
  538. fi
  539. rsync -a "$isolinuxbin" "$iso_dir"/isolinux/
  540. rsync -a "$vesamenu" "$iso_dir"/isolinux/
  541. # Add Refracta-specific boot help files
  542. if [[ $refracta_boot_help = "yes" ]] ; then
  543. cp -a /usr/lib/refractasnapshot/boot_help/* "$iso_dir"/isolinux/
  544. fi
  545. }
  546. # Let iso/, vmlinuz and initrd.img get copied, even if work_dir was saved,
  547. # in case they have changed.
  548. copy_kernel () {
  549. rsync -a "$iso_dir"/ "$work_dir"/iso/
  550. cp "$kernel_image" "$work_dir"/iso/live/
  551. cp "$initrd_image" "$work_dir"/iso/live/
  552. }
  553. copy_filesystem () {
  554. if [[ $limit_cpu = "yes" ]] ; then
  555. [[ $(type -p cpulimit) ]] || \
  556. while true ; do
  557. echo -n $"
  558. The cpulimit program is not installed. Your CPU will not be limited.
  559. Would you like to continue anyway? (y/N)
  560. "
  561. read ans
  562. case $ans in
  563. [Yy]*) break ;;
  564. *) exit 0 ;;
  565. esac
  566. done
  567. cpulimit -e rsync -l "$limit" &
  568. pid="$!"
  569. fi
  570. rsync -av / myfs/ ${rsync_option1} ${rsync_option2} ${rsync_option3} \
  571. --exclude="$work_dir" --exclude="$snapshot_dir" --exclude="$efi_work" --exclude-from="$snapshot_excludes"
  572. if [[ -n "$pid" ]] ; then
  573. kill "$pid"
  574. fi
  575. }
  576. edit_system () {
  577. # Truncate logs, remove archived logs.
  578. find myfs/var/log -name "*gz" -print0 | xargs -0r rm -f
  579. find myfs/var/log/ -type f -exec truncate -s 0 {} \;
  580. # Allow all fixed drives to be mounted with pmount
  581. if [[ $pmount_fixed = "yes" ]] ; then
  582. if [[ -f "$work_dir"/myfs/etc/pmount.allow ]]; then
  583. sed -i 's:#/dev/sd\[a-z\]:/dev/sd\[a-z\]:' "$work_dir"/myfs/etc/pmount.allow
  584. fi
  585. fi
  586. # Clear list of recently used files in geany for primary user.
  587. if [[ $clear_geany = "yes" ]] ; then
  588. sed -i 's/recent_files=.*;/recent_files=/' "$work_dir"/myfs/home/"$username"/.config/geany/geany.conf
  589. fi
  590. # Enable or disable password login through ssh for users (not root)
  591. # Remove obsolete live-config file
  592. if [[ -e "$work_dir"/myfs/lib/live/config/1161-openssh-server ]] ; then
  593. rm -f "$work_dir"/myfs/lib/live/config/1161-openssh-server
  594. fi
  595. sed -i 's/PermitRootLogin yes/PermitRootLogin prohibit-password/' "$work_dir"/myfs/etc/ssh/sshd_config
  596. if [[ $ssh_pass = "yes" ]] ; then
  597. sed -i 's|.*PasswordAuthentication.*no|PasswordAuthentication yes|' "$work_dir"/myfs/etc/ssh/sshd_config
  598. # sed -i 's|#.*PasswordAuthentication.*yes|PasswordAuthentication yes|' "$work_dir"/myfs/etc/ssh/sshd_config
  599. elif [[ $ssh_pass = "no" ]] ; then
  600. sed -i 's|.*PasswordAuthentication.*yes|PasswordAuthentication no|' "$work_dir"/myfs/etc/ssh/sshd_config
  601. fi
  602. # /etc/fstab should exist, even if it's empty,
  603. # to prevent error messages at boot
  604. touch "$work_dir"/myfs/etc/fstab
  605. # Blank out systemd machine id. If it does not exist, systemd-journald
  606. # will fail, but if it exists and is empty, systemd will automatically
  607. # set up a new unique ID.
  608. if [ -e "$work_dir"/myfs/etc/machine-id ]
  609. then
  610. rm -f "$work_dir"/myfs/etc/machine-id
  611. : > "$work_dir"/myfs/etc/machine-id
  612. fi
  613. # add some basic files to /dev
  614. mknod -m 622 "$work_dir"/myfs/dev/console c 5 1
  615. mknod -m 666 "$work_dir"/myfs/dev/null c 1 3
  616. mknod -m 666 "$work_dir"/myfs/dev/zero c 1 5
  617. mknod -m 666 "$work_dir"/myfs/dev/ptmx c 5 2
  618. mknod -m 666 "$work_dir"/myfs/dev/tty c 5 0
  619. mknod -m 444 "$work_dir"/myfs/dev/random c 1 8
  620. mknod -m 444 "$work_dir"/myfs/dev/urandom c 1 9
  621. chown -v root:tty "$work_dir"/myfs/dev/{console,ptmx,tty}
  622. ln -sv /proc/self/fd "$work_dir"/myfs/dev/fd
  623. ln -sv /proc/self/fd/0 "$work_dir"/myfs/dev/stdin
  624. ln -sv /proc/self/fd/1 "$work_dir"/myfs/dev/stdout
  625. ln -sv /proc/self/fd/2 "$work_dir"/myfs/dev/stderr
  626. ln -sv /proc/kcore "$work_dir"/myfs/dev/core
  627. mkdir -v "$work_dir"/myfs/dev/shm
  628. mkdir -v "$work_dir"/myfs/dev/pts
  629. chmod 1777 "$work_dir"/myfs/dev/shm
  630. # Clear configs from /etc/network/interfaces, wicd and NetworkManager
  631. # and netman, so they aren't stealthily included in the snapshot.
  632. if [[ -z $netconfig_opt ]] ; then
  633. echo "# The loopback network interface
  634. auto lo
  635. iface lo inet loopback
  636. " > "$work_dir"/myfs/etc/network/interfaces
  637. rm -f "$work_dir"/myfs/var/lib/wicd/configurations/*
  638. rm -f "$work_dir"/myfs/etc/wicd/wireless-settings.conf
  639. rm -f "$work_dir"/myfs/etc/NetworkManager/system-connections/*
  640. rm -f "$work_dir"/myfs/etc/network/wifi/*
  641. fi
  642. }
  643. get_filename () {
  644. # Need to define $filename here (moved up from genisoimage)
  645. # and use it as directory name to identify the build on the cdrom.
  646. # and put package list inside that directory
  647. if [[ $stamp = "datetime" ]]; then
  648. # use this variable so iso and sha256 have same time stamp
  649. filename="$snapshot_basename"-$(date +%Y%m%d_%H%M).iso
  650. else
  651. n=1
  652. while [[ -f "$snapshot_dir"/snapshot$n.iso ]]; do
  653. ((n++))
  654. done
  655. filename="$snapshot_basename"$n.iso
  656. fi
  657. }
  658. # create /boot and /efi for uefi.
  659. mkefi () {
  660. uefi_opt="-eltorito-alt-boot -e boot/grub/efiboot.img -isohybrid-gpt-basdat -no-emul-boot"
  661. #################################
  662. tempdir="$(mktemp -d /tmp/work_temp.XXXX)"
  663. # for initial grub.cfg
  664. mkdir -p "$tempdir"/boot/grub
  665. cat >"$tempdir"/boot/grub/grub.cfg <<EOF
  666. search --file --set=root /isolinux/isolinux.cfg
  667. set prefix=(\$root)/boot/grub
  668. source \$prefix/x86_64-efi/grub.cfg
  669. EOF
  670. #################################
  671. if ! [ -d "$efi_work" ] ; then
  672. mkdir "$efi_work"
  673. fi
  674. pushd "$efi_work"
  675. # start with empty directories.
  676. if [ -d "boot" ] ; then
  677. rm -rf boot
  678. fi
  679. if [ -d "efi" ] ; then
  680. rm -rf efi
  681. fi
  682. mkdir -p boot/grub/x86_64-efi
  683. mkdir -p efi/boot
  684. # copy splash
  685. cp "$iso_dir"/isolinux/splash.png boot/grub/splash.png
  686. # second grub.cfg file
  687. for i in $(ls /usr/lib/grub/x86_64-efi|grep part_|grep \.mod|sed 's/.mod//'); do echo "insmod $i" >> boot/grub/x86_64-efi/grub.cfg; done
  688. # Additional modules so we don't boot in blind mode. I don't know which ones are really needed.
  689. for i in efi_gop efi_uga ieee1275_fb vbe vga video_bochs video_cirrus jpeg png gfxterm ; do echo "insmod $i" >> boot/grub/x86_64-efi/grub.cfg ; done
  690. echo "source /boot/grub/grub.cfg" >> boot/grub/x86_64-efi/grub.cfg
  691. pushd "$tempdir"
  692. # make a tarred "memdisk" to embed in the grub image
  693. tar -cvf memdisk boot
  694. # make the grub image
  695. grub-mkimage -O "x86_64-efi" -m "memdisk" -o "bootx64.efi" -p '(memdisk)/boot/grub' search iso9660 configfile normal memdisk tar cat part_msdos part_gpt fat ext2 ntfs ntfscomp hfsplus chain boot linux
  696. popd
  697. # copy the grub image to efi/boot (to go later in the device's root)
  698. cp "$tempdir"/bootx64.efi efi/boot
  699. #######################
  700. ## Do the boot image "boot/grub/efiboot.img"
  701. dd if=/dev/zero of=boot/grub/efiboot.img bs=1K count=1440
  702. /sbin/mkdosfs -F 12 boot/grub/efiboot.img
  703. mkdir img-mnt
  704. mount -o loop boot/grub/efiboot.img img-mnt
  705. mkdir -p img-mnt/efi/boot
  706. cp "$tempdir"/bootx64.efi img-mnt/efi/boot/
  707. #######################
  708. # copy modules and font
  709. cp /usr/lib/grub/x86_64-efi/* boot/grub/x86_64-efi/
  710. # if this doesn't work try another font from the same place (grub's default, unicode.pf2, is much larger)
  711. # Either of these will work, and they look the same to me. Unicode seems to work with qemu. -fsr
  712. # cp /usr/share/grub/ascii.pf2 boot/grub/font.pf2
  713. cp /usr/share/grub/unicode.pf2 boot/grub/font.pf2
  714. # doesn't need to be root-owned
  715. chown -R 1000:1000 $(pwd) 2>/dev/null
  716. # Cleanup efi temps
  717. umount img-mnt
  718. rmdir img-mnt
  719. rm -rf "$tempdir"
  720. popd
  721. # Copy efi files to iso
  722. rsync -avx "$efi_work"/boot "$work_dir"/iso/
  723. rsync -avx "$efi_work"/efi "$work_dir"/iso/
  724. # Do the main grub.cfg (which gets loaded last):
  725. cp "$grub_template" "$work_dir"/iso/boot/grub/grub.cfg
  726. }
  727. add_extras () {
  728. # Prepend the dir name with a constant,
  729. # so you can find and delete the old ones
  730. # that might have different snapshot basenames.
  731. dir_prefix="pkglist"
  732. for dir in "$work_dir"/iso/"$dir_prefix"* ; do
  733. rm -r "$dir"
  734. done
  735. mkdir -p "$work_dir"/iso/"${dir_prefix}_${filename%.iso}"
  736. dpkg -l | egrep "ii|hi" | awk '{ print $2 }' > "$work_dir"/iso/"${dir_prefix}_${filename%.iso}"/package_list
  737. # Add the Release Notes to the iso
  738. if [[ -f /usr/share/doc/_Release_Notes/Release_Notes ]] ; then
  739. rsync -a /usr/share/doc/_Release_Notes/Release_Notes "$work_dir"/iso/
  740. fi
  741. }
  742. set_boot_options () {
  743. # Create the boot menu unless iso_dir is not default.
  744. if [ "$iso_dir" = "/usr/lib/refractasnapshot/iso" ] ; then
  745. sed -i "s:\${DISTRO}:$DISTRO:g" "$work_dir"/iso/isolinux/"$boot_menu"
  746. sed -i "s:\${netconfig_opt}:$netconfig_opt:g" "$work_dir"/iso/isolinux/"$boot_menu"
  747. sed -i "s:\${ifnames_opt}:$ifnames_opt:g" "$work_dir"/iso/isolinux/"$boot_menu"
  748. sed -i "s:\${username_opt}:$username_opt:g" "$work_dir"/iso/isolinux/"$boot_menu"
  749. fi
  750. if [[ $make_efi = "yes" ]] ; then
  751. sed -i "s:\${DISTRO}:$DISTRO:g" "$work_dir"/iso/boot/grub/grub.cfg
  752. sed -i "s:\${netconfig_opt}:$netconfig_opt:g" "$work_dir"/iso/boot/grub/grub.cfg
  753. sed -i "s:\${username_opt}:$username_opt:g" "$work_dir"/iso/boot/grub/grub.cfg
  754. sed -i "s:\${ifnames_opt}:$ifnames_opt:g" "$work_dir"/iso/boot/grub/grub.cfg
  755. fi
  756. }
  757. edit_boot_menus () {
  758. if [[ $edit_boot_menu = "yes" ]]; then
  759. echo $"
  760. You may now go to another virtual console to edit any files in the work
  761. directory, or hit ENTER and edit the boot menu.
  762. "
  763. read -p " "
  764. "$text_editor" "$work_dir"/iso/isolinux/"$boot_menu"
  765. if [[ $make_efi = "yes" ]] ; then
  766. "$text_editor" "$work_dir"/iso/boot/grub/grub.cfg
  767. fi
  768. fi
  769. }
  770. squash_filesystem () {
  771. echo "Squashing the filesystem..."
  772. if [[ $limit_cpu = "yes" ]] ; then
  773. [[ $(type -p cpulimit) ]] || \
  774. while true ; do
  775. echo -n $"
  776. The cpulimit program is not installed. Your CPU will not be limited.
  777. Would you like to continue anyway? (y/N)
  778. "
  779. read ans
  780. case $ans in
  781. [Yy]*) break ;;
  782. *) exit 0 ;;
  783. esac
  784. done
  785. cpulimit -e mksquashfs -l "$limit" &
  786. pid="$!"
  787. fi
  788. mksquashfs myfs/ iso/live/filesystem.squashfs ${mksq_opt} -noappend
  789. if [[ -n "$pid" ]] ; then
  790. kill "$pid"
  791. fi
  792. # This code is redundant, because $work_dir gets removed later, but
  793. # it might help by making more space on the hard drive for the iso.
  794. if [[ $save_work = "no" ]]; then
  795. rm -rf myfs
  796. fi
  797. }
  798. make_iso_fs () {
  799. # create the iso file, make it isohybrid
  800. # create sha256sum file for the iso
  801. echo $"Creating CD/DVD image file..."
  802. # If isohdpfx.bin gets moved again, maybe use: isohdpfx=$(find /usr/lib/ -name isohdpfx.bin)
  803. if [[ $make_isohybrid = "yes" ]]; then
  804. if [[ -f /usr/lib/syslinux/mbr/isohdpfx.bin ]] ; then
  805. isohybrid_opt="-isohybrid-mbr /usr/lib/syslinux/mbr/isohdpfx.bin"
  806. elif [[ -f /usr/lib/syslinux/isohdpfx.bin ]] ; then
  807. isohybrid_opt="-isohybrid-mbr /usr/lib/syslinux/isohdpfx.bin"
  808. elif [[ -f /usr/lib/ISOLINUX/isohdpfx.bin ]] ; then
  809. isohybrid_opt="-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin"
  810. else
  811. echo $"Can't create isohybrid. File: isohdpfx.bin not found. The resulting image will be a standard iso file."
  812. fi
  813. fi
  814. [[ -n "$volid" ]] || volid="liveiso"
  815. xorriso -as mkisofs -r -J -joliet-long -l -iso-level 3 ${isohybrid_opt} \
  816. -partition_offset 16 -V "$volid" -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot \
  817. -boot-load-size 4 -boot-info-table ${uefi_opt} -o "$snapshot_dir"/"$filename" iso/
  818. if [[ $make_sha256sum = "yes" ]]; then
  819. cd "$snapshot_dir"
  820. sha256sum "$filename" > "$filename".sha256
  821. cd "$work_dir"
  822. fi
  823. }
  824. cleanup () {
  825. if [[ $save_work = "no" ]]; then
  826. echo $"Cleaning..."
  827. cd /
  828. rm -rf "$work_dir"
  829. #else
  830. # rm "$work_dir"/iso/live/filesystem.squashfs
  831. fi
  832. }
  833. final_message () {
  834. echo -e $"\n\tAll finished!\n"
  835. }
  836. ######################################
  837. check_grub
  838. choose_task