From 604f3d64764270c052cfb43081ec522237bbdb75 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Fri, 5 May 2017 11:28:51 +0200 Subject: Massive add for all draft stuff to keep it in sync --- draft/other-tools/fog/fog-notes.txt | 148 ++ draft/other-tools/fog/fog.download | 261 ++++ draft/other-tools/fog/fog.upload | 216 +++ draft/other-tools/fog/funcs.sh | 2196 ++++++++++++++++++++++++++++++ draft/other-tools/fog/partition-funcs.sh | 811 +++++++++++ draft/other-tools/fog/procsfdisk.awk | 361 +++++ 6 files changed, 3993 insertions(+) create mode 100644 draft/other-tools/fog/fog-notes.txt create mode 100755 draft/other-tools/fog/fog.download create mode 100755 draft/other-tools/fog/fog.upload create mode 100644 draft/other-tools/fog/funcs.sh create mode 100644 draft/other-tools/fog/partition-funcs.sh create mode 100644 draft/other-tools/fog/procsfdisk.awk (limited to 'draft/other-tools/fog') diff --git a/draft/other-tools/fog/fog-notes.txt b/draft/other-tools/fog/fog-notes.txt new file mode 100644 index 0000000..61a7d12 --- /dev/null +++ b/draft/other-tools/fog/fog-notes.txt @@ -0,0 +1,148 @@ + + +./src/buildroot/package/fog/scripts/usr/share/fog/lib/funcs.sh + + + pigz $PIGZ_COMP < $fifo | split -a 3 -d -b 200m - ${file}. & + + + mainuuidfilename="$imagePath/d${disk_number}.original.uuids" + swapuuidfilename="$imagePath/d${disk_number}.original.swapuuids" + sfdiskoriginalpartitionfilename="$imagePath/d${disk_number}.partitions" + sfdisklegacyoriginalpartitionfilename="$imagePath/d${disk_number}.original.partitions" + sfdiskminimumpartitionfilename="$imagePath/d${disk_number}.minimum.partitions" + sgdiskoriginalpartitionfilename="$imagePath/d${disk_number}.sgdisk.original.partitions" + fixed_size_file="$imagePath/d${disk_number}.fixed_size_partitions" + hasgrubfilename="$imagePath/d${disk_number}.has_grub" + [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr" + [[ -n $sgdisk && $hasGRUB -eq 1 ]] && \ + mbr="$imagePath/d${disk_number}.grub.mbr" || \ + mbr="$imagePath/d${disk_number}.mbr" + ebrfilename="$path/d${disk_number}p${part_number}.ebr" + +# Save enough MBR and embedding area to capture all of GRUB +# Strategy is to capture EVERYTHING before the first partition. +# Then, leave a marker that this is a GRUB MBR for restoration. +# We could get away with less storage, but more details are required +# to parse the information correctly. It would make the process +# more complicated. + +# $1 is the disk +# $2 is the disk number +# $3 is the image path to save the file to. +# $4 is the determinator of sgdisk use or not +saveGRUB() { + + + # Determine the number of sectors to copy + # Hack Note: print $4+0 causes the column to be interpretted as a number + # so the comma is tossed + local count=$(sfdisk -d $disk 2>/dev/null | awk /start=\ *[1-9]/'{print $4+0}' | sort -n | head -n1) + + + local has_grub=$(dd if=$disk bs=512 count=1 2>&1 | grep -i 'grub') + + # Ensure that no more than 1MiB of data is copied (already have this size used elsewhere) + [[ $count -gt 2048 ]] && count=2048 + local mbrfilename="" + MBRFileName "$imagePath" "$disk_number" "mbrfilename" "$sgdisk" + dd if=$disk of=$mbrfilename count=$count bs=512 >/dev/null 2>&1 + +} + + + +hasGrubFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + local sgdisk="$3" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + hasgrubfilename="$imagePath/d${disk_number}.has_grub" + [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr" +} + +savePartitionTablesAndBootLoaders() { + + case $hasgpt in + 0) + strdots="Saving Partition Tables (MBR)" + case $osid in + 4|50|51) + [[ $disk_number -eq 1 ]] && strdots="Saving Partition Tables and GRUB (MBR)" + ;; + esac + dots "$strdots" + saveGRUB "$disk" "$disk_number" "$imagePath" + sfdisk -d $disk 2>/dev/null > $sfdiskfilename + [[ $have_extended_partition -ge 1 ]] && saveAllEBRs "$disk" "$disk_number" "$imagePath" + echo "Done" + ;; + 1) + dots "Saving Partition Tables (GPT)" + saveGRUB "$disk" "$disk_number" "$imagePath" "true" + sgdisk -b "$imagePath/d${disk_number}.mbr" $disk >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Error trying to save GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*" + fi + sfdisk -d $disk 2>/dev/null > $sfdiskfilename + echo "Done" + ;; + esac +}o + +clearPartitionTables() { + sgdisk -Z $disk >/dev/null 2>&1 +} + +restorePartitionTablesAndBootLoaders() { + if [[ $table_type == GPT ]]; then + dots "Restoring Partition Tables (GPT)" + restoreGRUB "$disk" "$disk_number" "$imagePath" "true" + sgdisk -gel $tmpMBR $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Error trying to restore GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*" + global_gptcheck="yes" + echo "Done" + else + [big cheat for MBR, dd, sfdisk for EBRs] + fi +} + + +savePartition() { + case $fstype in + swap) + echo " * Saving swap partition UUID" + swapUUIDFileName "$imagePath" "$disk_number" + saveSwapUUID "$swapuuidfilename" "$part" + ;; + *) + case $parttype in + 0x5|0xf) + echo " * Not capturing content of extended partition" + debugPause + EBRFileName "$imagePath" "$disk_number" "$part_number" + touch "$ebrfilename" + ;; + *) + echo " * Using partclone.$fstype" + debugPause + imgpart="$imagePath/d${disk_number}p${part_number}.img" + uploadFormat "$fifoname" "$imgpart" + partclone.$fstype -fsck-src-part -c -s $part -O $fifoname -N -f 1 + case $? in + 0) + mv ${imgpart}.000 $imgpart >/dev/null 2>&1 + echo " * Image Captured" + ;; + *) + handleError "Failed to complete capture (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + ;; + esac + ;; + esac + diff --git a/draft/other-tools/fog/fog.download b/draft/other-tools/fog/fog.download new file mode 100755 index 0000000..7190ebb --- /dev/null +++ b/draft/other-tools/fog/fog.download @@ -0,0 +1,261 @@ +#!/bin/bash +. /usr/share/fog/lib/funcs.sh +. /bin/fog.donate +. /bin/fog.checkin +. /bin/fog.mount +. /bin/fog.checkmount +. /bin/fog.checkimgvar +hd="" +disks="" +disk="" +parts="" +part="" +imagePath="/images/$img" +origmac=$mac +mac=$(getMACAddresses | base64) +. /bin/fog.inventory "true" +mac="$origmac" +origmac="" +layPartSize="-1s" +fog.statusreporter "$mac" "$web" & disown +statusReporter="$!" +fixed_size_partitions="" +echo " * Using Image: $img" +preparePartitions() { + echo " * Preparing Partition layout" + case $imgType in + [Nn]) + case $osid in + 4|50|51) + [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*" + prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + ;; + [1-2]) + [[ ! -f $imagePath && ! -f $imagePath/$img && ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*" + [[ -d $imagePath && -f $imagePath/$img ]] && imagePath="$imagePath/$img" + if [[ -d $imagePath ]]; then + prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + else + startsector="63s" + restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + dots "Removing partition" + parted -s $hd rm 1 >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not remove old partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + echo " * Attempting to expand/fill partitions" + dots "Recreating partition" + parted -s $hd mkpart primary ntfs 63s -- $layPartSize >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Could not create partition to fill disk ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Setting boot partition" + parted -s $hd set 1 boot on >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not make partition bootable ($0)\n Args Passed: $*" + fi + runPartprobe "$hd" + echo "Done" + debugPause + getPartitions "$hd" + for part in $parts; do + [[ -e $part ]] && break + done + fi + ;; + [5-7]|9) + [[ ! -d $imagePath && ! -f $imagePath/sys.img.000 ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*" + if [[ ! -f $imagePath/sys.img.000 ]]; then + prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + else + echo " * Using legacy style partition setup" + win7partcnt=1 + dots "Windows Boot Partition Exists" + if [[ ! -f $imagePath/gpt.bak && ! -f $imagePath/rec1.img.000 && ! -f $imagePath/rec.img.000 ]]; then + echo "No" + else + echo "Yes" + [[ -f $imagePath/rec.img.000 ]] && win7partcnt=2 + [[ -f $imagePath/rec.img.001 || -f $imagePath/gpt.bak ]] && win7partcnt=3 + fi + debugPause + echo " * Attempting to expand/fill partitions" + do_fill=0 + fillDiskWithPartitionsIsOK "$hd" "$imagePath" 1 + case $do_fill in + 1) + fillDiskWithPartitions "$hd" "$imagePath" 1 + echo "Done" + ;; + *) + startsector="2048s" + restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + case $win7partcnt in + 1) + dots "Removing partition" + parted -s $hd rm 1 >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not remove old partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Creating main partition" + parted -s $hd mkpart primary ntfs $startsector -- $layPartSize >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not recreate first partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Setting boot partition" + parted -s $hd set 1 boot on >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not make partition bootable ($0)\n Args Passed: $*" + fi + echo "Done" + ;; + 2) + dots "Removing main partition" + parted -s $hd rm 1 >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not remove old main partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Recreating recovery partition" + parted -s $hd mkpart primary ntfs $startsector 206847s >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not create recovery partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Recreating main partition" + parted -s $hd mkpart primary ntfs $defaultpart2start -- $layPartSize >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not recreate main partition ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Setting boot partition" + parted -s $hd set 1 boot on >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not make partition bootable ($0)\nArgsPassed: $*" + fi + echo "Done" + ;; + 3) + dots "Removing partition data" + sgdisk -Z $hd >/dev/null 2>&1 + sgdisk -gel $imagePath/gpt.bak $hd >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not recreate partitions ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + dots "Recreating sized out partitions" + sgdisk -x 3:$(sgdisk -E $hd) $hd >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not resize partitions ($0)\n Args Passed: $*" + fi + echo "Done" + ;; + esac + ;; + esac + debugPause + runPartprobe "$hd" + dots "Setting up partition variables" + getPartitions "$hd" + restoreparts="" + part_number=0 + for part in $parts; do + getPartitionNumber "$part" + [[ $part_number -le $win7partcnt ]] && restoreparts="$restoreparts $part" + done + echo "Done" + debugPause + fi + ;; + esac + ;; + mps) + [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*" + restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + runPartprobe "$hd" + gptcheck="$global_gptcheck" + ;; + mpa) + [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*" + getHardDisk "true" + disk_number=1 + for disk in $disks; do + restorePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType" + runPartprobe "$disk" + gptcheck="$global_gptcheck" + let disk_number+=1 + done + ;; + esac +} +putDataBack() { + runPartprobe "$hd" + getPartitions "$hd" + [[ -z $parts ]] && echo -e " * Seems like you are trying to restore to an empty disk. Be aware this will most probably cause trouble.\n" + echo " +--------------------------------+" + echo " | Attempting to deploy image |" + echo " +--------------------------------+" + [[ $imgFormat -eq 1 || $imgLegacy -eq 1 ]] && echo " | Using Partimage |" || echo " | Using Partclone |" + echo " +--------------------------------+" + [[ $mc == yes ]] && usleep 10000000 || usleep 3000000 + case $imgType in + dd) + restorePartition "$hd" 1 "$imagePath/$img.*" "$mc" + ;; + n|mps|mpa) + [[ $imgType == +(n|mps) ]] && disks="$hd" + case $osid in + [1-2]) + [[ ! -f $imagePath && ! -d $imagePath ]] && handleError "Fatal Error: Could not locate file ($0)\n Args Passed: $*" + ;; + [5-7]|9) + [[ ! -d $imagePath && ! -f $imagePath/sys.img.000 ]] && handleError "Fatal Error: Could not locate file ($0)\n Args Passed: $*" + ;; + 4|50|51) + [[ ! -d $imagePath ]] && handleError "Fatal Error: could not locate file ($0)\n Args Passed: $*" + ;; + esac + performRestore "$disks" "$imagePath" "$imgPartitionType" "$mc" + ;; + esac +} +findHDDInfo +[[ $nombr -eq 1 ]] && echo " * Skipping partition layout (Single Partition restore)" || preparePartitions +[[ $imgPartitionType != mbr ]] && putDataBack || echo " * Skipping partition restore (MBR Only)" +completeTasking diff --git a/draft/other-tools/fog/fog.upload b/draft/other-tools/fog/fog.upload new file mode 100755 index 0000000..8a80ae8 --- /dev/null +++ b/draft/other-tools/fog/fog.upload @@ -0,0 +1,216 @@ +#!/bin/bash +. /usr/share/fog/lib/funcs.sh +. /bin/fog.checkin +. /bin/fog.mount +. /bin/fog.checkmount +. /bin/fog.checkimgvar +imagePath="/images/$macWinSafe" +parts="" +part="" +disks="" +disk="" +hd="" +echo " * Preparing to send image file to server" +percent="$pct" +[[ $pct -lt 5 || $pct -ge 100 ]] && percent=5 +[[ $pct -lt 10 ]] && percent="0$pct" +fog.statusreporter "$mac" "$web" & disown +statusReporter="$!" +prepareUploadLocation "$imagePath" +echo " * Using Image: $img" +# resizable image type +# discover windows partitions +# remove pagefile and hibernate file +# validate XP partition location +# save original partition table +# save MBR +# shrink filesystems and partitions +# save GRUB +# save shrunken partition table +# clone filesystems +# restore original MBR and partition table +# expand filesystems +beginUpload() { + case $imgType in + [Nn]) + validResizeOS + runPartprobe "$hd" + getPartitions "$hd" + [[ $osid == @([1-2]|[4-7]|9) ]] && win7partcnt=$(echo $parts | wc -w) + dots "Checking for fixed partitions" + part_number=0 + for part in $parts; do + fsTypeSetting "$part" + getPartitionNumber "$part" + case $fstype in + ntfs|extfs) + continue + ;; + *) + fixed_size_partitions="$fixed_size_partitions:$part_number" + ;; + esac + done + echo "Done" + debugPause + dots "Getting Windows/Linux Partition Count" + countPartTypes "$hd" "ntfs" "ntfscnt" + countPartTypes "$hd" "extfs" "extfscnt" + if [[ $ntfscnt -eq 0 && $extfscnt -eq 0 ]]; then + echo "Failed" + debugPause + handleError "No resizable partitions found ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + echo " * NTFS Partition count of: $ntfscnt" + debugPause + echo " * EXTFS Partition count of: $extfscnt" + debugPause + case $osid in + [4-7]|9|50|51) + echo " * Setting up any additional fixed parts" + [[ $((ntfscnt + extfscnt)) -gt 0 && $part_number -gt 1 ]] && fixed_size_partitions="$fixed_size_partitions:1" + part_number=0 + for part in $parts; do + getPartitionNumber "$part" + fsTypeSetting "$part" + [[ $fstype != ntfs ]] && continue + dots "Mounting partition ($part)" + if [[ ! -d /bcdstore ]]; then + mkdir -p /bcdstore >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError " * Could not create mount location ($0->${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + ntfs-3g -o remove_hiberfile,rw $part /bcdstore >/tmp/ntfs-mount-output 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError " * Could not mount $part ($0->${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)" + ;; + esac + dots "BCD exists on $part in /bcdstore" + if [[ ! -f /bcdstore/Boot/BCD ]]; then + umount /bcdstore >/dev/null 2>&1 + echo "No" + debugPause + else + umount /bcdstore >/dev/null 2>&1 + echo "Yes" + debugPause + if [[ $part_number -gt 1 ]]; then + for ((increment=1; increment < $part_number; increment++)); do + fixed_size_partitions="$fixed_size_partitions:$increment" + done + fi + fi + done + ;; + esac + # All: + # save the list of fixed size partitions + fixed_size_partitions=$(echo $fixed_size_partitions | tr ':' '\n' | uniq | tr '\n' ':' | sed 's/:$//g') + echo "$fixed_size_partitions" > "$imagePath/d1.fixed_size_partitions" + # Windows 2000/XP, Vista, 7, 8, 8.1, Linux: + # Save unmodified partition table for download use + # Start filesytem type record + dots "Saving original partition table" + saveOriginalPartitions "$hd" "$imagePath" 1 + swapuuidfilename="" + swapUUIDFileName "$imagePath" 1 + mainuuidfilename="" + mainUUIDFileName "$imagePath" 1 + echo -n "" > "$imagePath/d1.original.fstypes" + echo -n "" > $swapuuidfilename + echo "Done" + debugPause + echo " * Saving original disk/parts UUIDs" + debugPause + saveUUIDInformation "$hd" "$mainuuidfilename" + echo " * Shrinking Partitions on disk" + debugPause + for part in $parts; do + clearMountedDevices "$part" + removePageFile "$part" + shrinkPartition "$part" "$imagePath/d1.original.fstypes" "$fixed_size_partitions" + done + echo " * Saving shrunken partition table" + debugPause + sfdiskminimumpartitionfilename="" + sfdiskMinimumPartitionFileName "$imagePath" 1 + savePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" "$sfdiskminimumpartitionfilename" + echo " * Processing Hard Disk: $hd" + for part in $parts; do + savePartition "$part" 1 "$imagePath" "$imgPartitionType" + done + dots "Restoring Original Partition Layout" + restoreOriginalPartitions "$hd" "$imagePath" 1 + runPartprobe "$hd" + echo "Done" + debugPause + [[ $osid -eq 2 ]] && correctVistaMBR "$hd" + getPartitions "$hd" + for part in $parts; do + expandPartition "$part" "$fixed_size_partitions" + done + ;; + mps) + echo " * Processing Hard Disk: $hd" + echo " * Saving original disk/parts UUIDs" + debugPause + mainuuidfilename="" + mainUUIDFileName "$imagePath" 1 + saveUUIDInformation "$hd" "$mainuuidfilename" + savePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" + getPartitions "$hd" + for part in $parts; do + savePartition "$part" 1 "$imagePath" "$imgPartitionType" + done + ;; + mpa) + disk_number=1 + for disk in $disks; do + debugPause + echo " * Processing Hard Disk: $disk" + echo " * Saving original disk/parts UUIDs" + debugPause + mainuuidfilename="" + mainUUIDFileName "$imagePath" $disk_number + saveUUIDInformation "$disk" "$mainuuidfilename" + savePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType" + runPartprobe "$disk" + getPartitions "$disk" + for part in $parts; do + savePartition "$part" "$disk_number" "$imagePath" "$imgPartitionType" + done + echo " * Disk $disk complete" + let disk_number+=1 + done + ;; + dd) + imgpart="$imagePath/$img" + mkfifo /tmp/pigz1 >/dev/null 2>&1 + uploadFormat "/tmp/pigz1" "$imgpart" + partclone.imager -c -s "$hd" -O /tmp/pigz1 -N -f 1 + rm /tmp/pigz1 >/dev/null 2>&1 + clearScreen + ;; + esac +} +findHDDInfo +echo " * Now FOG will attempt to capture the image using Partclone" +debugPause +beginUpload +completeTasking diff --git a/draft/other-tools/fog/funcs.sh b/draft/other-tools/fog/funcs.sh new file mode 100644 index 0000000..e6f574c --- /dev/null +++ b/draft/other-tools/fog/funcs.sh @@ -0,0 +1,2196 @@ +#!/bin/bash +. /usr/share/fog/lib/partition-funcs.sh +REG_LOCAL_MACHINE_XP="/ntfs/WINDOWS/system32/config/system" +REG_LOCAL_MACHINE_7="/ntfs/Windows/System32/config/SYSTEM" +# 1 to turn on massive debugging of partition table restoration +ismajordebug=0 +#If a sub shell gets invoked and we lose kernel vars this will reimport them +oIFS=$IFS +for var in $(cat /proc/cmdline); do + IFS=$oIFS + read name value <<< $(echo "$var" | grep =.* | awk -F= '{name=$1;$1="";gsub(/[ \t]+$/,"",$0);gsub(/^[ \t]+/,"",$0); gsub(/[+][_][+]/," ",$0); value=$0; print name; print value;}') + IFS=$'\n' + [[ -z $value ]] && continue + value=$(echo $value | sed 's/\"//g') + printf -v "$name" -- "$value" +done +IFS=$oIFS +### If USB Boot device we need a way to get the kernel args properly +[[ $boottype == usb && -f /tmp/hinfo.txt ]] && . /tmp/hinfo.txt +# Below Are non parameterized functions +# These functions will run without any arguments +# +# Clears thes creen unless its a debug task +clearScreen() { + case $isdebug in + [Yy][Ee][Ss]|[Yy]) + clear + ;; + esac +} +# Displays the nice banner along with the running version +displayBanner() { + version=$(wget -qO - http://${web}service/getversion.php 2>/dev/null) + echo " +------------------------------------------+" + echo " | ..#######:. ..,#,.. .::##::. |" + echo " |.:###### .:;####:......;#;.. |" + echo " |...##... ...##;,;##::::.##... |" + echo " | ,# ...##.....##:::## ..:: |" + echo " | ## .::###,,##. . ##.::#.:######::.|" + echo " |...##:::###::....#. .. .#...#. #...#:::. |" + echo " |..:####:.. ..##......##::## .. # |" + echo " | # . ...##:,;##;:::#: ... ##.. |" + echo " | .# . .:;####;::::.##:::;#:.. |" + echo " | # ..:;###.. |" + echo " | |" + echo " +------------------------------------------+" + echo " | Free Computer Imaging Solution |" + echo " +------------------------------------------+" + echo " | Credits: http://fogproject.org/Credits |" + echo " | http://fogproject.org/Credits |" + echo " | Released under GPL Version 3 |" + echo " +------------------------------------------+" + echo " Version: $version" +} +# Gets all system mac addresses except for loopback +getMACAddresses() { + read ifaces <<< $(/sbin/ip -4 -o addr | awk -F'([ /])+' '/global/ {print $2}' | tr '[:space:]' '|' | sed -e 's/^[|]//g' -e 's/[|]$//g') + read mac_addresses <<< $(/sbin/ip -0 -o addr | awk "/$ifaces/ {print \$11}" | tr '[:space:]' '|' | sed -e 's/^[|]//g' -e 's/[|]$//g') + echo $mac_addresses +} +# Verifies that there is a network interface +verifyNetworkConnection() { + dots "Verifying network interface configuration" + local count=$(/sbin/ip addr | awk -F'[ /]+' '/global/{print $3}' | wc -l) + if [[ -z $count || $count -lt 1 ]]; then + echo "Failed" + debugPause + handleError "No network interfaces found (${FUNCNAME[0]})\n Args Passed: $*" + fi + echo "Done" + debugPause +} +# Verifies that the OS is valid for resizing +validResizeOS() { + [[ $osid != @([1-2]|4|[5-7]|9|50|51) ]] && handleError " * Invalid operating system id: $osname ($osid) (${FUNCNAME[0]})\n Args Passed: $*" +} +# Gets the information from the system for inventory +doInventory() { + sysman=$(dmidecode -s system-manufacturer) + sysproduct=$(dmidecode -s system-product-name) + sysversion=$(dmidecode -s system-version) + sysserial=$(dmidecode -s system-serial-number) + systype=$(dmidecode -t 3 | grep Type:) + biosversion=$(dmidecode -s bios-version) + biosvendor=$(dmidecode -s bios-vendor) + biosdate=$(dmidecode -s bios-release-date) + mbman=$(dmidecode -s baseboard-manufacturer) + mbproductname=$(dmidecode -s baseboard-product-name) + mbversion=$(dmidecode -s baseboard-version) + mbserial=$(dmidecode -s baseboard-serial-number) + mbasset=$(dmidecode -s baseboard-asset-tag) + cpuman=$(dmidecode -s processor-manufacturer) + cpuversion=$(dmidecode -s processor-version) + cpucurrent=$(dmidecode -t 4 | grep 'Current Speed:' | head -n1) + cpumax=$(dmidecode -t 4 | grep 'Max Speed:' | head -n1) + mem=$(cat /proc/meminfo | grep MemTotal) + hdinfo=$(hdparm -i $hd 2>/dev/null | grep Model=) + caseman=$(dmidecode -s chassis-manufacturer) + casever=$(dmidecode -s chassis-version) + caseserial=$(dmidecode -s chassis-serial-number) + casesasset=$(dmidecode -s chassis-asset-tag) + sysman64=$(echo $sysman | base64) + sysproduct64=$(echo $sysproduct | base64) + sysversion64=$(echo $sysversion | base64) + sysserial64=$(echo $sysserial | base64) + systype64=$(echo $systype | base64) + biosversion64=$(echo $biosversion | base64) + biosvendor64=$(echo $biosvendor | base64) + biosdate64=$(echo $biosdate | base64) + mbman64=$(echo $mbman | base64) + mbproductname64=$(echo $mbproductname | base64) + mbversion64=$(echo $mbversion | base64) + mbserial64=$(echo $mbserial | base64) + mbasset64=$(echo $mbasset | base64) + cpuman64=$(echo $cpuman | base64) + cpuversion64=$(echo $cpuversion | base64) + cpucurrent64=$(echo $cpucurrent | base64) + cpumax64=$(echo $cpumax | base64) + mem64=$(echo $mem | base64) + hdinfo64=$(echo $hdinfo | base64) + caseman64=$(echo $caseman | base64) + casever64=$(echo $casever | base64) + caseserial64=$(echo $caseserial | base64) + casesasset64=$(echo $casesasset | base64) +} +# Gets the location of the SAM registry if found +getSAMLoc() { + local path="" + local paths="/ntfs/WINDOWS/system32/config/SAM /ntfs/Windows/System32/config/SAM" + for path in $paths; do + [[ ! -f $path ]] && continue + sam="$path" && break + done +} +# Appends dots to the end of string up to 50 characters. +# Makes the output more aligned and organized. +# +# $1 String to append dots to +dots() { + local str="$*" + [[ -z $str ]] && handleError "No string passed (${FUNCNAME[0]})\n Args Passed: $*" + local pad=$(printf "%0.1s" "."{1..50}) + printf " * %s%*.*s" "$str" 0 $((50-${#str})) "$pad" +} +# Enables write caching on the disk passed +# If the disk does not support write caching this does nothing +# +# $1 is the drive +enableWriteCache() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + wcache=$(hdparm -W $disk 2>/dev/null | tr -d '[[:space:]]' | awk -F= '/.*write-caching=/{print $2}') + if [[ -z $wcache || $wcache == notsupported ]]; then + echo " * Write caching not supported" + debugPause + return + fi + dots "Enabling write cache" + hdparm -W1 $disk >/dev/null 2>&1 + case $? in + 0) + echo "Enabled" + ;; + *) + echo "Failed" + debugPause + handleWarning "Could not set caching status (${FUNCNAME[0]})" + return + ;; + esac + debugPause +} +# Expands partitions, as needed/capable +# +# $1 is the partition +# $2 is the fixed size partitions (can be empty) +expandPartition() { + local part="$1" + local fixed="$2" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + local part_number=0 + getDiskFromPartition "$part" + getPartitionNumber "$part" + local is_fixed=$(echo $fixed | awk "/(^$part_number:|:$part_number:|:$part_number$|^$part_number$)/{print 1}") + if [[ $is_fixed -eq 1 ]]; then + echo " * Not expanding ($part) fixed size" + debugPause + return + fi + local fstype="" + fsTypeSetting $part + case $fstype in + ntfs) + dots "Resizing $fstype volume ($part)" + ntfsresize $part -f -b -P /dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not resize $part (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause + resetFlag "$part" + ;; + extfs) + dots "Resizing $fstype volume ($part)" + e2fsck -fp $part >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not check before resize (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + resize2fs $part >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not resize $part (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + e2fsck -fp $part >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not check after resize (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + ;; + *) + echo " * Not expanding ($part -- $fstype)" + debugPause + ;; + esac + debugPause + runPartprobe "$disk" +} +# Gets the filesystem type of the partition passed +# +# $1 is the partition +fsTypeSetting() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local blk_fs=$(blkid -po udev $part | awk -F= /FS_TYPE=/'{print $2}') + case $blk_fs in + btrfs) + fstype="btrfs" + ;; + ext[2-4]) + fstype="extfs" + ;; + hfsplus) + fstype="hfsp" + ;; + ntfs) + fstype="ntfs" + ;; + swap) + fstype="swap" + ;; + vfat) + fstype="fat" + ;; + xfs) + fstype="xfs" + ;; + *) + fstype="imager" + ;; + esac +} +# Gets the disk part table UUID +# +# $1 is the disk +getDiskUUID() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + diskuuid=$(blkid -po udev $disk | awk -F= '/PART_TABLE_UUID=/{print $2}') +} +# Gets the partition entry name +# +# $1 is the partition +getPartName() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + partname=$(blkid -po udev $part | awk -F= '/PART_ENTRY_NAME=/{print $2}') +} +# Gets the partition entry type +# +# $1 is the partition +getPartType() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + parttype=$(blkid -po udev $part | awk -F= '/PART_ENTRY_TYPE=/{print $2}') +} +# Gets the partition fs UUID +# +# $1 is the partition +getPartFSUUID() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + partfsuuid=$(blkid -po udev $part | awk -F= '/FS_UUID=/{print $2}') +} +# Gets the partition entry UUID +# +# $1 is the partition +getPartUUID() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + partuuid=$(blkid -po udev $part | awk -F= '/PART_ENTRY_UUID=/{print $2}') +} +# Gets the entry schemed (dos, gpt, etc...) +# +# $1 is the partition +getPartitionEntryScheme() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + scheme=$(blkid -po udev $part | awk -F= '/PART_ENTRY_SCHEME=/{print $2}') +} +# Checks if the partition is dos extended (mbr with logical parts) +# +# $1 is the partition +partitionIsDosExtended() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local scheme="" + getPartitionEntryScheme "$part" + debugEcho "scheme = $scheme" 1>&2 + case $scheme in + dos) + echo "no" + ;; + *) + local parttype="" + getPartType "$part" + debugEcho "parttype = $parttype" 1>&2 + [[ $parttype == +(0x5|0xf) ]] && echo "yes" || echo "no" + ;; + esac + debugPause +} +# Returns the block size of a partition +# +# $1 is the partition +# $2 is the variable to set +getPartBlockSize() { + local part="$1" + local varVar="$2" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*" + printf -v "$varVar" $(blockdev --getpbsz $part) +} +# Prepares location info for uploads +# +# $1 is the image path +prepareUploadLocation() { + local imagePath="$1" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + dots "Preparing backup location" + if [[ ! -d $imagePath ]]; then + mkdir -p $imagePath >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Failed to create image capture path (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + echo "Done" + debugPause + dots "Setting permission on $imagePath" + chmod -R 777 $imagePath >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Failed to set permissions (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause + dots "Removing any pre-existing files" + rm -Rf $imagePath/* >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not clean files (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause +} +# Shrinks partitions for upload (resizable images only) +# +# $1 is the partition +# $2 is the fstypes file location +# $3 is the fixed partition numbers empty ok +shrinkPartition() { + local part="$1" + local fstypefile="$2" + local fixed="$3" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $fstypefile ]] && handleError "No type file passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + local part_number=0 + getDiskFromPartition "$part" + getPartitionNumber "$part" + local is_fixed=$(echo $fixed | awk "/(^$part_number:|:$part_number:|:$part_number$|^$part_number$)/{print 1}") + if [[ $is_fixed -eq 1 ]]; then + echo " * Not shrinking ($part) fixed size" + debugPause + return + fi + local fstype="" + fsTypeSetting "$part" + echo "$part $fstype" >> $fstypefile + local size=0 + local tmpoutput="" + local sizentfsresize=0 + local sizeextresize=0 + local sizefd=0 + local tmp_success="" + local test_string="" + local do_resizefs=0 + local do_resizepart=0 + local extminsize=0 + local block_size=0 + local sizeextresize=0 + local adjustedfdsize=0 + local part_block_size=0 + case $fstype in + ntfs) + ntfsresize -f -i -v -P $part >/tmp/tmpoutput.txt 2>&1 + if [[ ! $? -eq 0 ]]; then + handleError " * (${FUNCNAME[0]})\n Args Passed: $*\n\nFatal Error, unable to find size data out on $part. Cmd: ntfsresize -f -i -v -P $part" + fi + tmpoutput=$(cat /tmp/tmpoutput.txt) + size=$(cat /tmp/tmpoutput.txt | grep "You might resize" | cut -d" " -f5) + [[ -z $size ]] && handleError " * (${FUNCNAME[0]})\n Args Passed: $*\n\nFatal Error, Unable to determine possible ntfs size\n * To better help you debug we will run the ntfs resize\n\t but this time with full output, please wait!\n\t $(cat /tmp/tmpoutput.txt)" + rm /tmp/tmpoutput.txt >/dev/null 2>&1 + sizentfsresize=$((size / 1000)) + let sizentfsresize+=300000 + sizentfsresize=$((sizentfsresize * 1${percent} / 100)) + sizefd=$((sizentfsresize * 103 / 100)) + echo " * Possible resize partition size: $sizentfsresize k" + dots "Running resize test $part" + ntfsresize -f -n -s ${sizentfsresize}k $part /tmp/tmpoutput.txt 2>&1 + local ntfsstatus="$?" + tmpoutput=$(cat /tmp/tmpoutput.txt) + test_string=$(cat /tmp/tmpoutput.txt | egrep -io "(ended successfully|bigger than the device size|volume size is already OK)" | tr -d '[[:space:]]') + echo "Done" + debugPause + rm /tmp/tmpoutput.txt >/dev/null 2>&1 + case $test_string in + endedsuccessfully) + echo " * Resize test was successful" + do_resizefs=1 + do_resizepart=1 + ntfsstatus=0 + ;; + biggerthanthedevicesize) + echo " * Not resizing filesystem $part (part too small)" + ntfsstatus=0 + ;; + volumesizeisalreadyOK) + echo " * Not resizing filesystem $part (already OK)" + do_resizepart=1 + ntfsstatus=0 + ;; + esac + [[ ! $ntfsstatus -eq 0 ]] && handleError "Resize test failed!\n $tmpoutput\n (${FUNCNAME[0]})\n Args Passed: $*" + if [[ $do_resizefs -eq 1 ]]; then + debugPause + dots "Resizing filesystem" + ntfsresize -f -s ${sizentfsresize}k $part < /usr/share/fog/lib/EOFNTFS >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not resize disk (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + if [[ $do_resizepart -eq 1 ]]; then + debugPause + dots "Resizing partition $part" + getPartBlockSize "$part" "part_block_size" + case $osid in + [1-2]|4) + resizePartition "$part" "$sizentfsresize" "$imagePath" + [[ $osid -eq 2 ]] && correctVistaMBR "$disk" + ;; + [5-7]|9) + [[ $part_number -eq $win7partcnt ]] && part_start=$(blkid -po udev $part 2>/dev/null | awk -F= '/PART_ENTRY_OFFSET=/{printf("%.0f\n",$2*'$part_block_size'/1000)}') || part_start=1048576 + if [[ -z $part_start || $part_start -lt 1 ]]; then + echo "Failed" + debugPause + handleError "Unable to determine disk start location (${FUNCNAME[0]})\n Args Passed: $*" + fi + adjustedfdsize=$((sizefd + part_start)) + resizePartition "$part" "$adjustedfdsize" "$imagePath" + ;; + esac + echo "Done" + fi + resetFlag "$part" + ;; + extfs) + dots "Checking $fstype volume ($part)" + e2fsck -fp $part >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "e2fsck failed to check $part (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause + extminsize=$(resize2fs -P $part 2>/dev/null | awk -F': ' '{print $2}') + block_size=$(dumpe2fs -h $part 2>/dev/null | awk /^Block\ size:/'{print $3}') + size=$((extminsize * block_size)) + sizeextresize=$((size * 103 / 100 / 1024)) + [[ -z $sizeextresize || $sizeextresize -lt 1 ]] && handleError "Error calculating the new size of extfs ($part) (${FUNCNAME[0]})\n Args Passed: $*" + dots "Shrinking $fstype volume ($part)" + resize2fs $part -M >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not shrink $fstype volume ($part) (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause + dots "Shrinking $part partition" + resizePartition "$part" "$sizeextresize" "$imagePath" + echo "Done" + debugPause + dots "Resizing $fstype volume ($part)" + resize2fs $part >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could resize $fstype volume ($part) (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + e2fsck -fp $part >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not check expanded volume ($part) (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + ;; + *) + echo " * Not shrinking ($part $fstype)" + ;; + esac + debugPause +} +# Resets the dirty bits on a partition +# +# $1 is the part +resetFlag() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local fstype="" + fsTypeSetting "$part" + case $fstype in + ntfs) + dots "Clearing ntfs flag" + ntfsfix -b -d $part >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + ;; + esac + ;; + esac +} +# Counts the partitions containing the fs type as passed +# +# $1 is the disk +# $2 is the part type to look for +# $3 is the variable to store the count into. This is +# a variable variable +countPartTypes() { + local disk="$1" + local parttype="$2" + local varVar="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $parttype ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*" + local count=0 + local fstype="" + local parts="" + local part="" + getPartitions "$disk" + for part in $parts; do + fsTypeSetting "$part" + case $fstype in + $parttype) + let count+=1 + ;; + esac + done + printf -v "$varVar" "$count" +} +# Writes the image to the disk +# +# $1 = Source File +# $2 = Target +# $3 = mc task or not (not required) +writeImage() { + local file="$1" + local target="$2" + local mc="$3" + [[ -z $target ]] && handleError "No target to place image passed (${FUNCNAME[0]})\n Args Passed: $*" + mkfifo /tmp/pigz1 + case $mc in + yes) + udp-receiver --nokbd --portbase $port --ttl 32 --mcast-rdv-address $storageip 2>/dev/null >/tmp/pigz1 & + ;; + *) + [[ -z $file ]] && handleError "No source file passed (${FUNCNAME[0]})\n Args Passed: $*" + cat $file >/tmp/pigz1 & + ;; + esac + if [[ $imgFormat -eq 1 || $imgLegacy -eq 1 ]]; then + echo " * Imaging using Partimage" + pigz -d -c /tmp/status.fog + else + echo " * Imaging using Partclone" + pigz -d -c /dev/null 2>&1 +} +# Gets the valid restore parts. They're only +# valid if the partition data exists for +# the partitions on the server +# +# $1 = Disk (e.g. /dev/sdb) +# $2 = Disk number (e.g. 1) +# $3 = ImagePath (e.g. /net/foo) +getValidRestorePartitions() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local setrestoreparts="$4" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local valid_parts="" + local parts="" + local part="" + local imgpart="" + local part_number=0 + getPartitions "$disk" + for part in $parts; do + getPartitionNumber "$part" + [[ $imgPartitionType != all && $imgPartitionType != $part_number ]] && continue + case $osid in + [1-2]) + [[ ! -f $imagePath ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*" || imgpart="$imagePath" + ;; + 4|[5-7]|9) + [[ ! -f $imagePath/sys.img.000 ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*" + if [[ -z $imgpart ]]; then + case $win7partcnt in + 1) + [[ $part_number -eq 1 ]] && imgpart="$imagePath/sys.img.*" + ;; + 2) + [[ $part_number -eq 1 ]] && imgpart="$imagePath/rec.img.000" + [[ $part_number -eq 2 ]] && imgpart="$imagePath/sys.img.*" + ;; + 3) + [[ $part_number -eq 1 ]] && imgpart="$imagePath/rec.img.000" + [[ $part_number -eq 2 ]] && imgpart="$imagePath/rec.img.001" + [[ $part_number -eq 3 ]] && imgpart="$imagePath/sys.img.*" + ;; + esac + fi + ;; + *) + imgpart="$imagePath/d${disk_number}p${part_number}.img*" + ;; + esac + ls $imgpart >/dev/null 2>&1 + [[ $? -eq 0 ]] && valid_parts="$valid_parts $part" + done + [[ -z $setrestoreparts ]] && restoreparts=$(echo $valid_parts | uniq | sort -V) || restoreparts="$(echo $setrestoreparts | uniq | sort -V)" +} +# Makes all swap partitions and sets uuid's in linux setups +# +# $1 = Disk (e.g. /dev/sdb) +# $2 = Disk number (e.g. 1) +# $3 = ImagePath (e.g. /net/foo) +# $4 = ImagePartitionType (e.g. all, mbr, 1, 2, 3, etc.) +makeAllSwapSystems() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local imgPartitionType="$4" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No image partition type passed (${FUNCNAME[0]})\n Args Passed: $*" + local swapuuidfilename="" + swapUUIDFileName "$imagePath" "$disk_number" + local parts="" + local part="" + local part_number=0 + getPartitions "$disk" + for part in $parts; do + getPartitionNumber "$part" + [[ $imgPartitionType == all || $imgPartitionType -eq $part_number ]] && makeSwapSystem "$swapuuidfilename" "$part" + done + runPartprobe "$disk" +} +# Changes the hostname on windows systems +# +# $1 = Partition +changeHostname() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $hostname || $hostearly -eq 0 ]] && return + REG_HOSTNAME_KEY1="\ControlSet001\Services\Tcpip\Parameters\NV Hostname" + REG_HOSTNAME_KEY2="\ControlSet001\Services\Tcpip\Parameters\Hostname" + REG_HOSTNAME_KEY3="\ControlSet001\Services\Tcpip\Parameters\NV HostName" + REG_HOSTNAME_KEY4="\ControlSet001\Services\Tcpip\Parameters\HostName" + REG_HOSTNAME_KEY5="\ControlSet001\Control\ComputerName\ActiveComputerName\ComputerName" + REG_HOSTNAME_KEY6="\ControlSet001\Control\ComputerName\ComputerName\ComputerName" + REG_HOSTNAME_KEY7="\ControlSet001\services\Tcpip\Parameters\NV Hostname" + REG_HOSTNAME_KEY8="\ControlSet001\services\Tcpip\Parameters\Hostname" + REG_HOSTNAME_KEY9="\ControlSet001\services\Tcpip\Parameters\NV HostName" + REG_HOSTNAME_KEY10="\ControlSet001\services\Tcpip\Parameters\HostName" + REG_HOSTNAME_KEY11="\CurrentControlSet\Services\Tcpip\Parameters\NV Hostname" + REG_HOSTNAME_KEY12="\CurrentControlSet\Services\Tcpip\Parameters\Hostname" + REG_HOSTNAME_KEY13="\CurrentControlSet\Services\Tcpip\Parameters\NV HostName" + REG_HOSTNAME_KEY14="\CurrentControlSet\Services\Tcpip\Parameters\HostName" + REG_HOSTNAME_KEY15="\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName" + REG_HOSTNAME_KEY16="\CurrentControlSet\Control\ComputerName\ComputerName\ComputerName" + REG_HOSTNAME_KEY17="\CurrentControlSet\services\Tcpip\Parameters\NV Hostname" + REG_HOSTNAME_KEY18="\CurrentControlSet\services\Tcpip\Parameters\Hostname" + REG_HOSTNAME_KEY19="\CurrentControlSet\services\Tcpip\Parameters\NV HostName" + REG_HOSTNAME_KEY20="\CurrentControlSet\services\Tcpip\Parameters\HostName" + dots "Mounting directory" + if [[ ! -d /ntfs ]]; then + mkdir -p /ntfs >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*" + fi + fi + umount /ntfs >/dev/null 2>&1 + ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)" + ;; + esac + if [[ ! -f /usr/share/fog/lib/EOFREG ]]; then + key1="$REG_HOSTNAME_KEY1" + key2="$REG_HOSTNAME_KEY2" + key3="$REG_HOSTNAME_KEY3" + key4="$REG_HOSTNAME_KEY4" + key5="$REG_HOSTNAME_KEY5" + key6="$REG_HOSTNAME_KEY6" + key7="$REG_HOSTNAME_KEY7" + key8="$REG_HOSTNAME_KEY8" + key9="$REG_HOSTNAME_KEY9" + key10="$REG_HOSTNAME_KEY10" + key11="$REG_HOSTNAME_KEY11" + key12="$REG_HOSTNAME_KEY12" + key13="$REG_HOSTNAME_KEY13" + key14="$REG_HOSTNAME_KEY14" + key15="$REG_HOSTNAME_KEY15" + key16="$REG_HOSTNAME_KEY16" + key17="$REG_HOSTNAME_KEY17" + key18="$REG_HOSTNAME_KEY18" + key19="$REG_HOSTNAME_KEY19" + key20="$REG_HOSTNAME_KEY20" + case $osid in + 1) + regfile="$REG_LOCAL_MACHINE_XP" + ;; + 2|4|[5-7]|9) + regfile="$REG_LOCAL_MACHINE_7" + ;; + esac + echo "ed $key1" >/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key2" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key3" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key4" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key5" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key6" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key7" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key8" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key9" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key10" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key11" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key12" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key13" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key14" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key15" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key16" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key17" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key18" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key19" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "ed $key20" >>/usr/share/fog/lib/EOFREG + echo "$hostname" >>/usr/share/fog/lib/EOFREG + echo "q" >> /usr/share/fog/lib/EOFREG + echo "y" >> /usr/share/fog/lib/EOFREG + echo >> /usr/share/fog/lib/EOFREG + fi + if [[ -e $regfile ]]; then + dots "Changing hostname" + reged -e $regfile < /usr/share/fog/lib/EOFREG >/dev/null 2>&1 + case $? in + [0-2]) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + umount /ntfs >/dev/null 2>&1 + echo " * Failed to change hostname" + return + ;; + esac + fi + rm -rf /usr/share/fog/lib/EOFREG + umount /ntfs >/dev/null 2>&1 +} +# Fixes windows 7/8 boot, though may need +# to be updated to only impact windows 7 +# in which case we need a more dynamic method +# +# $1 is the partition +fixWin7boot() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ $osid != [5-7] ]] && return + local fstype="" + fsTypeSetting "$part" + [[ $fstype != ntfs ]] && return + dots "Mounting partition" + if [[ ! -d /bcdstore ]]; then + mkdir -p /bcdstore >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + ntfs-3g -o remove_hiberfile,rw $part /bcdstore >/tmp/ntfs-mount-output 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)" + ;; + esac + if [[ ! -f /bcdstore/Boot/BCD ]]; then + umount /bcdstore >/dev/null 2>&1 + return + fi + dots "Backing up and replacing BCD" + mv /bcdstore/Boot/BCD{,.bak} >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + umount /bcdstore >/dev/null 2>&1 + echo " * Could not create backup" + return + ;; + esac + cp /usr/share/fog/BCD /bcdstore/Boot/BCD >/dev/null 2>&1 + case $? in + 0) + echo "Done" + debugPause + umount /bcdstore >/dev/null 2>&1 + ;; + *) + echo "Failed" + debugPause + umount /bcdstore >/dev/null 2>&1 + echo " * Could not copy our bcd file" + return + ;; + esac + umount /bcdstore >/dev/null 2>&1 +} +# Clears out windows hiber and page files +# +# $1 is the partition +clearMountedDevices() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + if [[ ! -d /ntfs ]]; then + mkdir -p /ntfs >/dev/null 2>&1 + case $? in + 0) + umount /ntfs >/dev/null 2>&1 + ;; + *) + handleError "Could not create mount point /ntfs (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + case $osid in + 4|[5-7]|9) + local fstype="" + fsTypeSetting "$part" + REG_HOSTNAME_MOUNTED_DEVICES_7="\MountedDevices" + if [[ ! -f /usr/share/fog/lib/EOFMOUNT ]]; then + echo "cd $REG_HOSTNAME_MOUNTED_DEVICES_7" >/usr/share/fog/lib/EOFMOUNT + echo "dellallv" >>/usr/share/fog/lib/EOFMOUNT + echo "q" >>/usr/share/fog/lib/EOFMOUNT + echo "y" >>/usr/share/fog/lib/EOFMOUNT + echo >> /usr/share/fog/lib/EOFMOUNT + fi + case $fstype in + ntfs) + dots "Clearing part ($part)" + ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)" + ;; + esac + if [[ ! -f $REG_LOCAL_MACHINE_7 ]]; then + echo "Reg file not found" + debugPause + umount /ntfs >/dev/null 2>&1 + return + fi + reged -e $REG_LOCAL_MACHINE_7 /dev/null 2>&1 + case $? in + [0-2]) + echo "Done" + debugPause + umount /ntfs >/dev/null 2>&1 + ;; + *) + echo "Failed" + debugPause + /umount /ntfs >/dev/null 2>&1 + echo " * Could not clear partition $part" + return + ;; + esac + ;; + esac + ;; + esac +} +# Only removes the page file +# +# $1 is the device name of the windows system partition +removePageFile() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local fstype="" + fsTypeSetting "$part" + [[ ! $ignorepg -eq 1 ]] && return + case $osid in + [1-2]|4|[5-7]|[9]|50|51) + case $fstype in + ntfs) + dots "Mounting partition ($part)" + if [[ ! -d /ntfs ]]; then + mkdir -p /ntfs >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fi + umount /ntfs >/dev/null 2>&1 + ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)" + ;; + esac + if [[ -f /ntfs/pagefile.sys ]]; then + dots "Removing page file" + rm -rf /ntfs/pagefile.sys >/dev/null 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + echo " * Could not delete the page file" + ;; + esac + fi + if [[ -f /ntfs/hiberfil.sys ]]; then + dots "Removing hibernate file" + rm -rf /ntfs/hiberfil.sys >/dev/null 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + umount /ntfs >/dev/null 2>&1 + echo " * Could not delete the hibernate file" + ;; + esac + fi + umount /ntfs >/dev/null 2>&1 + ;; + esac + ;; + esac +} +# Sets OS mbr, as needed, and returns the Name +# based on the OS id passed. +# +# $1 the osid to determine the os and mbr +determineOS() { + local osid="$1" + [[ -z $osid ]] && handleError "No os id passed (${FUNCNAME[0]})\n Args Passed: $*" + case $osid in + 1) + osname="Windows XP" + mbrfile="/usr/share/fog/mbr/xp.mbr" + ;; + 2) + osname="Windows Vista" + mbrfile="/usr/share/fog/mbr/vista.mbr" + ;; + 3) + osname="Windows 98" + mbrfile="" + ;; + 4) + osname="Windows (Other)" + mbrfile="" + ;; + 5) + osname="Windows 7" + mbrfile="/usr/share/fog/mbr/win7.mbr" + defaultpart2start="105906176B" + ;; + 6) + osname="Windows 8" + mbrfile="/usr/share/fog/mbr/win8.mbr" + defaultpart2start="368050176B" + ;; + 7) + osname="Windows 8.1" + mbrfile="/usr/share/fog/mbr/win8.mbr" + defaultpart2start="368050176B" + ;; + 8) + osname="Apple Mac OS" + mbrfile="" + ;; + 9) + osname="Windows 10" + mbrfile="" + ;; + 50) + osname="Linux" + mbrfile="" + ;; + 51) + osname="Chromium OS" + mbrfile="" + ;; + 99) + osname="Other OS" + mbrfile="" + ;; + *) + handleError " * Invalid OS ID ($osid) (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac +} +# Converts the string (seconds) passed to human understanding +# +# $1 the seconds to convert +sec2string() { + local T="$1" + [[ -z $T ]] && handleError "No string passed (${FUNCNAME[0]})\n Args Passed: $*" + local d=$((T/60/60/24)) + local H=$((T/60/60%24)) + local i=$((T/60%60)) + local s=$((T%60)) + local dayspace='' + local hourspace='' + local minspace='' + [[ $H > 0 ]] && dayspace=' ' + [[ $i > 0 ]] && hourspace=':' + [[ $s > 0 ]] && minspace=':' + (($d > 0)) && printf '%d day%s' "$d" "$dayspace" + (($H > 0)) && printf '%d%s' "$H" "$hourspace" + (($i > 0)) && printf '%d%s' "$i" "$minspace" + (($s > 0)) && printf '%d' "$s" +} +# Returns the disk based off the partition passed +# +# $1 is the partition to grab the disk from +getDiskFromPartition() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + disk=$(echo $part | sed 's/p\?[0-9]\+$//g') +} +# Returns the number of the partition passed +# +# $1 is the partition to get the partition number for +getPartitionNumber() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + part_number=$(echo $part | grep -o '[0-9]*$') +} +# $1 is the partition to search for. +getPartitions() { + local disk="$1" + [[ -z $disk ]] && disk="$hd" + [[ -z $disk ]] && handleError "No disk found (${FUNCNAME[0]})\n Args Passed: $*" + parts=$(lsblk -I 3,8,9,179,259 -lpno KNAME,TYPE $disk | awk '{if ($2 ~ /part/ || $2 ~ /md/) print $1}' | sort -V | uniq) +} +# Gets the hard drive on the host +# Note: This function makes a best guess +getHardDisk() { + [[ -n $fdrive ]] && hd=$(echo $fdrive) + [[ -n $hd ]] && return + local devs=$(lsblk -dpno KNAME -I 3,8,9,179,259 | uniq | sort -V) + disks=$(echo $devs) + [[ -z $disks ]] && handleError "Cannot find disk on system (${FUNCNAME[0]})\n Args Passed: $*" + [[ $1 == true ]] && return + for hd in $disks; do + break + done +} +# Finds the hard drive info and set's up the type +findHDDInfo() { + case $imgType in + [Nn]|mps|dd) + dots "Looking for Hard Disk" + getHardDisk + if [[ -z $hd ]]; then + echo "Failed" + debugPause + handleError "Could not find hard disk ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + case $type in + down) + diskSize=$(lsblk --bytes -dplno SIZE -I 3,8,9,179,259 $hd) + [[ $diskSize -gt 2199023255552 ]] && layPartSize="2tB" + echo " * Using Disk: $hd" + [[ $imgType == +([nN]) ]] && validResizeOS + enableWriteCache "$hd" + ;; + up) + dots "Reading Partition Tables" + runPartprobe "$hd" + getPartitions "$hd" + if [[ -z $parts ]]; then + echo "Failed" + debugPause + handleError "Could not find partitions ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + ;; + esac + echo " * Using Hard Disk: $hd" + ;; + mpa) + dots "Looking for Hard Disks" + getHardDisk "true" + if [[ -z $disks ]]; then + echo "Failed" + debugPause + handleError "Could not find any disks ($0)\n Args Passed: $*" + fi + echo "Done" + debugPause + case $type in + up) + for disk in $disks; do + dots "Reading Partition Tables on $disk" + getPartitions "$disk" + if [[ -z $parts ]]; then + echo "Failed" + debugPause + echo " * No partitions for disk $disk" + debugPause + continue + fi + echo "Done" + debugPause + done + ;; + esac + echo " * Using Disks: $disks" + ;; + esac +} + +# Imaging complete +completeTasking() { + case $type in + up) + chmod -R 777 "$imagePath" >/dev/null 2>&1 + killStatusReporter + . /bin/fog.imgcomplete + ;; + down) + killStatusReporter + if [[ -f /images/postdownloadscripts/fog.postdownload ]]; then + postdownpath="/images/postdownloadscripts/" + . ${postdownpath}fog.postdownload + fi + [[ $capone -eq 1 ]] && exit 0 + if [[ $osid == +([1-2]|4|[5-7]|9) ]]; then + for disk in $disks; do + getPartitions "$disk" + for part in $parts; do + fsTypeSetting "$part" + [[ $fstype == ntfs ]] && changeHostname "$part" + done + done + fi + . /bin/fog.imgcomplete + ;; + esac +} +# Corrects mbr layout for Vista OS +# +# $1 is the disk to correct for +correctVistaMBR() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + dots "Correcting Vista MBR" + dd if=$disk of=/tmp.mbr count=1 bs=512 >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not create backup (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + xxd /tmp.mbr /tmp.mbr.txt >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "xxd command failed (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + rm /tmp.mbr >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Couldn't remove /tmp.mbr file (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + fogmbrfix /tmp.mbr.txt /tmp.mbr.fix.txt >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "fogmbrfix failed to operate (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + rm /tmp.mbr.txt >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not remove the text file (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + xxd -r /tmp.mbr.fix.txt /mbr.mbr >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not run second xxd command (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + rm /tmp.mbr.fix.txt >/dev/null 2>&1 + case $? in + 0) + ;; + *) + echo "Failed" + debugPause + handleError "Could not remove the fix file (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + dd if=/mbr.mbr of="$disk" count=1 bs=512 >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not apply fixed MBR (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause +} +# Prints an error with visible information +# +# $1 is the string to inform what went wrong +handleError() { + local str="$1" + local parts="" + local part="" + echo "##############################################################################" + echo "# #" + echo "# An error has been detected! #" + echo "# #" + echo "##############################################################################" + echo -e "$str" + # + # expand the file systems in the restored partitions + # + # Windows 7, 8, 8.1: + # Windows 2000/XP, Vista: + # Linux: + if [[ -n $2 ]]; then + case $osid in + [1-2]|4|[5-7]|9|50|51) + if [[ -n "$hd" ]]; then + getPartitions "$hd" + for part in $parts; do + expandPartition "$part" + done + fi + ;; + esac + fi + if [[ -z $isdebug ]]; then + echo "##############################################################################" + echo "# #" + echo "# Computer will reboot in 1 minute #" + echo "# #" + echo "##############################################################################" + usleep 60000000 + else + debugPause + fi + exit 1 +} +# Prints a visible banner describing an issue but not breaking +# +# $1 The string to inform the user what the problem is +handleWarning() { + local str="$1" + echo "##############################################################################" + echo "# #" + echo "# A warning has been detected! #" + echo "# #" + echo "##############################################################################" + echo -e "$str" + echo "##############################################################################" + echo "# #" + echo "# Will continue in 1 minute #" + echo "# #" + echo "##############################################################################" + usleep 60000000 + debugPause +} +# Re-reads the partition table of the disk passed +# +# $1 is the disk +runPartprobe() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + umount /ntfs /bcdstore >/dev/null 2>&1 + udevadm settle + blockdev --rereadpt $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to read back partitions (${FUNCNAME[0]})\n Args Passed: $*" +} +# Sends a command list to a file for use when debugging +# +# $1 The string of the command needed to run. +debugCommand() { + local str="$1" + case $isdebug in + [Yy][Ee][Ss]|[Yy]) + echo -e "$str" >> /tmp/cmdlist + ;; + esac +} +# Escapes the passed item where needed +# +# $1 the item that needs to be escaped +escapeItem() { + local item="$1" + echo $item | sed -r 's%/%\\/%g' +} +# uploadFormat +# Description: +# Tells the system what format to upload in, whether split or not. +# Expects first argument to be the fifo to send to. +# Expects part of the filename in the case of resizable +# will append 000 001 002 automatically +# +# $1 The fifo name (file in file out) +# $2 The file to upload into on the server +uploadFormat() { + local fifo="$1" + local file="$2" + [[ -z $fifo ]] && handleError "Missing file in file out (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "Missing file name to store (${FUNCNAME[0]})\n Args Passed: $*" + [[ ! -e $fifo ]] && mkfifo $fifo >/dev/null 2>&1 + case $imgFormat in + 2) + pigz $PIGZ_COMP < $fifo | split -a 3 -d -b 200m - ${file}. & + ;; + *) + pigz $PIGZ_COMP < $fifo > ${file}.000 & + ;; + esac +} +# Thank you, fractal13 Code Base +# +# Save enough MBR and embedding area to capture all of GRUB +# Strategy is to capture EVERYTHING before the first partition. +# Then, leave a marker that this is a GRUB MBR for restoration. +# We could get away with less storage, but more details are required +# to parse the information correctly. It would make the process +# more complicated. +# +# See the discussion about the diskboot.img and the sector list +# here: http://banane-krumm.de/bootloader/grub2.html +# +# Expects: +# the device name (e.g. /dev/sda) as the first parameter, +# the disk number (e.g. 1) as the second parameter +# the directory to store images in (e.g. /image/dev/xyz) as the third parameter +# +# $1 is the disk +# $2 is the disk number +# $3 is the image path to save the file to. +# $4 is the determinator of sgdisk use or not +saveGRUB() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local sgdisk="$4" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + # Determine the number of sectors to copy + # Hack Note: print $4+0 causes the column to be interpretted as a number + # so the comma is tossed + local count=$(sfdisk -d $disk 2>/dev/null | awk /start=\ *[1-9]/'{print $4+0}' | sort -n | head -n1) + local has_grub=$(dd if=$disk bs=512 count=1 2>&1 | grep -i 'grub') + local hasgrubfilename="" + if [[ -n $has_grub ]]; then + hasGrubFileName "$imagePath" "$disk_number" "$sgdisk" + touch $hasgrubfilename + fi + # Ensure that no more than 1MiB of data is copied (already have this size used elsewhere) + [[ $count -gt 2048 ]] && count=2048 + local mbrfilename="" + MBRFileName "$imagePath" "$disk_number" "mbrfilename" "$sgdisk" + dd if=$disk of=$mbrfilename count=$count bs=512 >/dev/null 2>&1 +} +# Checks for the existence of the grub embedding area in the image directory. +# Echos 1 for true, and 0 for false. +# +# Expects: +# the device name (e.g. /dev/sda) as the first parameter, +# the disk number (e.g. 1) as the second parameter +# the directory images stored in (e.g. /image/xyz) as the third parameter +# $1 is the disk +# $2 is the disk number +# $3 is the image path +# $4 is the sgdisk determinator +hasGRUB() { + local disk_number="$1" + local imagePath="$2" + local sgdisk="$3" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local hasgrubfilename="" + hasGrubFileName "$imagePath" "$disk_number" "$sgdisk" + hasGRUB=0 + [[ -e $hasgrubfilename ]] && hasGRUB=1 +} +# Restore the grub boot record and all of the embedding area data +# necessary for grub2. +# +# Expects: +# the device name (e.g. /dev/sda) as the first parameter, +# the disk number (e.g. 1) as the second parameter +# the directory images stored in (e.g. /image/xyz) as the third parameter +# $1 is the disk +# $2 is the disk number +# $3 is the image path +# $4 is the sgdisk determinator +restoreGRUB() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local sgdisk="$4" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local tmpMBR="" + MBRFileName "$imagePath" "$disk_number" "tmpMBR" "$sgdisk" + local count=$(du -B 512 $tmpMBR | awk '{print $1}') + [[ $count -eq 8 ]] && count=1 + dd if=$tmpMBR of=$disk bs=512 count=$count >/dev/null 2>&1 + runPartprobe "$disk" +} +# Waits for enter if system is debug type +debugPause() { + case $isdebug in + [Yy][Ee][Ss]|[Yy]) + echo " * Press [Enter] key to continue" + read -p "$*" + ;; + *) + return + ;; + esac +} +debugEcho() { + local str="$*" + case $isdebug in + [Yy][Ee][Ss]|[Yy]) + echo "$str" + ;; + *) + return + ;; + esac +} +majorDebugEcho() { + [[ $ismajordebug -gt 1 ]] && echo "$*" +} +majorDebugPause() { + [[ ! $ismajordebug -gt 0 ]] && return + echo " * Press [Enter] key to continue" + read -p "$*" +} +swapUUIDFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + swapuuidfilename="$imagePath/d${disk_number}.original.swapuuids" +} +mainUUIDFileName() { + local imagePath="$1" + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + mainuuidfilename="$imagePath/d${disk_number}.original.uuids" +} +sfdiskPartitionFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdiskoriginalpartitionfilename="$imagePath/d${disk_number}.partitions" +} +sfdiskLegacyOriginalPartitionFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdisklegacyoriginalpartitionfilename="$imagePath/d${disk_number}.original.partitions" +} +sfdiskMinimumPartitionFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdiskminimumpartitionfilename="$imagePath/d${disk_number}.minimum.partitions" +} +sfdiskOriginalPartitionFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdiskPartitionFileName "$imagePath" "$disk_number" +} +sgdiskOriginalPartitionFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + sgdiskoriginalpartitionfilename="$imagePath/d${disk_number}.sgdisk.original.partitions" +} +fixedSizePartitionsFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + fixed_size_file="$imagePath/d${disk_number}.fixed_size_partitions" +} +hasGrubFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + local sgdisk="$3" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + hasgrubfilename="$imagePath/d${disk_number}.has_grub" + [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr" +} +MBRFileName() { + local imagePath="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + local varVar="$3" + local sgdisk="$4" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*" + local mbr="" + local hasGRUB=0 + hasGRUB "$disk_number" "$imagePath" "$sgdisk" + [[ -n $sgdisk && $hasGRUB -eq 1 ]] && mbr="$imagePath/d${disk_number}.grub.mbr" || mbr="$imagePath/d${disk_number}.mbr" + case $type in + down) + [[ ! -f $mbr && -n $mbrfile ]] && mbr="$mbrfile" + printf -v "$varVar" "$mbr" + [[ -z $mbr ]] && handleError "Image store corrupt, unable to locate MBR, no default file specified (${FUNCNAME[0]})\n Args Passed: $*\n $varVar Variable set to: ${!varVar}" + [[ ! -f $mbr ]] && handleError "Image store corrupt, unable to locate MBR, no file found (${FUNCNAME[0]})\n Args Passed: $*\n Variable set to: ${!varVar}\n $varVar Variable set to: ${!varVar}" + ;; + up) + printf -v "$varVar" "$mbr" + ;; + esac +} +EBRFileName() { + local path="$1" # e.g. /net/dev/foo + local disk_number="$2" # e.g. 1 + local part_number="$3" # e.g. 5 + [[ -z $path ]] && handleError "No path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $part_number ]] && handleError "No partition number passed (${FUNCNAME[0]})\n Args Passed: $*" + ebrfilename="$path/d${disk_number}p${part_number}.ebr" +} +tmpEBRFileName() { + local disk_number="$1" + local part_number="$2" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $part_number ]] && handleError "No partition number passed (${FUNCNAME[0]})\n Args Passed: $*" + local ebrfilename="" + EBRFileName "/tmp" "$disk_number" "$disk_number" + tmpebrfilename="$ebrfilename" +} +# +# Works for MBR/DOS or GPT style partition tables +# Only saves PT information if the type is "all" or "mbr" +# +# For MBR/DOS style PT +# Saves the MBR as everything before the start of the first partition (512+ bytes) +# This includes the DOS MBR or GRUB. Don't know about other bootloaders +# This includes the 4 primary partitions +# The EBR of extended and logical partitions is actually the first 512 bytes of +# the partition, so we don't need to save/restore them here. +# +# +savePartitionTablesAndBootLoaders() { + local disk="$1" # e.g. /dev/sda + local disk_number="$2" # e.g. 1 + local imagePath="$3" # e.g. /net/dev/foo + local osid="$4" # e.g. 50 + local imgPartitionType="$5" + local sfdiskfilename="$6" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No img part type passed (${FUNCNAME[0]})\n Args Passed: $*" + if [[ -z $sfdiskfilename ]]; then + sfdiskPartitionFileName "$imagePath" "$disk_number" + sfdiskfilename="$sfdiskoriginalpartitionfilename" + fi + local hasgpt=0 + hasGPT "$disk" + local have_extended_partition=0 # e.g. 0 or 1-n (extended partition count) + local strdots="" + [[ $hasgpt -eq 0 ]] && have_extended_partition=$(sfdisk -l $disk 2>/dev/null | egrep "^${disk}.* (Extended|W95 Ext'd \(LBA\))$" | wc -l) + runPartprobe "$disk" + case $hasgpt in + 0) + strdots="Saving Partition Tables (MBR)" + case $osid in + 4|50|51) + [[ $disk_number -eq 1 ]] && strdots="Saving Partition Tables and GRUB (MBR)" + ;; + esac + dots "$strdots" + saveGRUB "$disk" "$disk_number" "$imagePath" + sfdisk -d $disk 2>/dev/null > $sfdiskfilename + [[ $have_extended_partition -ge 1 ]] && saveAllEBRs "$disk" "$disk_number" "$imagePath" + echo "Done" + ;; + 1) + dots "Saving Partition Tables (GPT)" + saveGRUB "$disk" "$disk_number" "$imagePath" "true" + sgdisk -b "$imagePath/d${disk_number}.mbr" $disk >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Error trying to save GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*" + fi + sfdisk -d $disk 2>/dev/null > $sfdiskfilename + echo "Done" + ;; + esac + runPartprobe "$disk" + debugPause +} +clearPartitionTables() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ $nombr -eq 1 ]] && return + dots "Erasing current MBR/GPT Tables" + sgdisk -Z $disk >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + 2) + echo "Done, but cleared corrupted partition." + ;; + *) + echo "Failed" + debugPause + handleError "Error trying to erase partition tables (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + runPartprobe "$disk" + debugPause +} +# Restores the partition tables and boot loaders +# +# $1 is the disk +# $2 is the disk number +# $3 is the image path +# $4 is the osid +# $5 is the image partition type +restorePartitionTablesAndBootLoaders() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local osid="$4" + local imgPartitionType="$5" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No image part type passed (${FUNCNAME[0]})\n Args Passed: $*" + local tmpMBR="" + local strdots="" + if [[ $nombr -eq 1 ]]; then + echo " * Skipping partition tables and MBR" + debugPause + return + fi + clearPartitionTables "$disk" + majorDebugEcho "Partition table should be empty now." + majorDebugShowCurrentPartitionTable "$disk" "$disk_number" + majorDebugPause + MBRFileName "$imagePath" "$disk_number" "tmpMBR" + [[ ! -f $tmpMBR ]] && handleError "Image Store Corrupt: Unable to locate MBR (${FUNCNAME[0]})\n Args Passed: $*" + local table_type="" + getDesiredPartitionTableType "$imagePath" "$disk_number" + majorDebugEcho "Trying to restore to $table_type partition table." + if [[ $table_type == GPT ]]; then + dots "Restoring Partition Tables (GPT)" + restoreGRUB "$disk" "$disk_number" "$imagePath" "true" + sgdisk -gel $tmpMBR $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Error trying to restore GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*" + global_gptcheck="yes" + echo "Done" + else + case $osid in + 50|51) + strdots="Restoring Partition Tables and GRUB (MBR)" + ;; + *) + strdots="Restoring Partition Tables (MBR)" + ;; + esac + dots "$strdots" + restoreGRUB "$disk" "$disk_number" "$imagePath" + echo "Done" + debugPause + majorDebugShowCurrentPartitionTable "$disk" "$disk_number" + majorDebugPause + ebrcount=$(ls -1 $imagePath/*.ebr 2>/dev/null | wc -l) + [[ $ebrcount -gt 0 ]] && restoreAllEBRs "$disk" "$disk_number" "$imagePath" "$imgPartitionType" + local sfdiskoriginalpartitionfilename="" + local sfdisklegacyoriginalpartitionfilename="" + sfdiskPartitionFileName "$imagePath" "$disk_number" + sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number" + if [[ -r $sfdiskoriginalpartitionfilename ]]; then + dots "Inserting Extended partitions" + sfdisk $disk < $sfdiskoriginalpartitionfilename >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + ;; + esac + elif [[ -e $sfdisklegacyoriginalpartitionfilename ]]; then + dots "Extended partitions (legacy)" + sfdisk $disk < $sfdisklegacyoriginalpartitionfilename >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + ;; + esac + else + echo " * No extended partitions" + fi + fi + debugPause + runPartprobe "$disk" + majorDebugShowCurrentPartitionTable "$disk" "$disk_number" + majorDebugPause +} +savePartition() { + local part="$1" + local disk_number="$2" + local imagePath="$3" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local part_number=0 + getPartitionNumber "$part" + local fstype="" + local parttype="" + local imgpart="" + local fifoname="/tmp/pigz1" + if [[ $imgPartitionType != all && $imgPartitionType != $part_number ]]; then + echo " * Skipping partition $part ($part_number)" + debugPause + return + fi + echo " * Processing Partition: $part ($part_number)" + debugPause + fsTypeSetting "$part" + getPartType "$part" + local ebrfilename="" + local swapuuidfilename="" + case $fstype in + swap) + echo " * Saving swap partition UUID" + swapUUIDFileName "$imagePath" "$disk_number" + saveSwapUUID "$swapuuidfilename" "$part" + ;; + *) + case $parttype in + 0x5|0xf) + echo " * Not capturing content of extended partition" + debugPause + EBRFileName "$imagePath" "$disk_number" "$part_number" + touch "$ebrfilename" + ;; + *) + echo " * Using partclone.$fstype" + debugPause + imgpart="$imagePath/d${disk_number}p${part_number}.img" + uploadFormat "$fifoname" "$imgpart" + partclone.$fstype -fsck-src-part -c -s $part -O $fifoname -N -f 1 + case $? in + 0) + mv ${imgpart}.000 $imgpart >/dev/null 2>&1 + echo " * Image Captured" + ;; + *) + handleError "Failed to complete capture (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + ;; + esac + ;; + esac + rm -rf $fifoname >/dev/null 2>&1 + debugPause +} +restorePartition() { + local part="$1" + local disk_number="$2" + local imagePath="$3" + local mc="$4" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + if [[ $imgPartitionType != all && $imgPartitionType != $part_number ]]; then + echo " * Skipping partition: $part ($part_number)" + debugPause + return + fi + local imgpart="" + local ebrfilename="" + local disk="" + local part_number=0 + getDiskFromPartition "$part" + getPartitionNumber "$part" + echo " * Processing Partition: $part ($part_number)" + debugPause + case $imgType in + dd) + imgpart="$imagePath" + ;; + n|mps|mpa) + case $osid in + [1-2]) + [[ -f $imagePath ]] && imgpart="$imagePath" || imgpart="$imagePath/d${disk_number}p${part_number}.img*" + ;; + 4|8|50|51) + imgpart="$imagePath/d${disk_number}p${part_number}.img*" + ;; + [5-7]|9) + [[ ! -f $imagePath/sys.img.000 ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*" + if [[ -z $imgpart ]] ;then + case $win7partcnt in + 1) + imgpart="$imagePath/sys.img.*" + ;; + 2) + case $part_number in + 1) + imgpart="$imagePath/rec.img.000" + ;; + 2) + imgpart="$imagePath/sys.img.*" + ;; + esac + ;; + 3) + case $part_number in + 1) + imgpart="$imagePath/rec.img.000" + ;; + 2) + imgpart="$imagePath/rec.img.001" + ;; + 3) + imgpart="$imagePath/sys.img.*" + ;; + esac + ;; + esac + fi + ;; + esac + ;; + *) + handleError "Invalid Image Type $imgType (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + ls $imgpart >/dev/null 2>&1 + if [[ ! $? -eq 0 ]]; then + EBRFileName "$imagePath" "$disk_number" "$part_number" + [[ -e $ebrfilename ]] && echo " * Not deploying content of extended partition" || echo " * Partition File Missing: $imgpart" + runPartprobe "$disk" + return + fi + writeImage "$imgpart" "$part" "$mc" + runPartprobe "$disk" + resetFlag "$part" +} +runFixparts() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + dots "Attempting fixparts" + fixparts $disk /dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not fix partition layout (${FUNCNAME[0]})\n Args Passed: $*" "yes" + ;; + esac + debugPause + runPartprobe "$disk" +} +killStatusReporter() { + dots "Stopping FOG Status Reporter" + kill -9 $statusReporter >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + ;; + esac + debugPause +} +prepareResizeDownloadPartitions() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local osid="$4" + local imgPartitionType="$5" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No image partition type passed (${FUNCNAME[0]})\n Args Passed: $*" + if [[ $nombr -eq 1 ]]; then + echo -e " * Skipping partition preperation\n" + debugPause + return + fi + restorePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType" + local do_fill=0 + fillDiskWithPartitionsIsOK "$disk" "$imagePath" "$disk_number" + majorDebugEcho "Filling disk = $do_fill" + dots "Attempting to expand/fill partitions" + if [[ $do_fill -eq 0 ]]; then + echo "Failed" + debugPause + handleError "Fatal Error: Could not resize partitions (${FUNCNAME[0]})\n Args Passed: $*" + fi + fillDiskWithPartitions "$disk" "$imagePath" "$disk_number" + echo "Done" + debugPause + runPartprobe "$disk" +} +# $1 is the disks +# $2 is the image path +# $3 is the image partition type (either all or partition number) +# $4 is the flag to say whether this is multicast or not +performRestore() { + local disks="$1" + local disk="" + local imagePath="$2" + local imgPartitionType="$3" + local mc="$4" + [[ -z $disks ]] && handleError "No disks passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk_number=1 + local part_number=0 + local restoreparts="" + local mainuuidfilename="" + [[ $imgType =~ [Nn] ]] && local tmpebrfilename="" + for disk in $disks; do + mainuuidfilename="" + mainUUIDFileName "$imagePath" "$disk_number" + getValidRestorePartitions "$disk" "$disk_number" "$imagePath" "$restoreparts" + [[ -z $restoreparts ]] && handleError "No image file(s) found that would match the partition(s) to be restored (${FUNCNAME[0]})\n Args Passed: $*" + for restorepart in $restoreparts; do + getPartitionNumber "$restorepart" + [[ $imgType =~ [Nn] ]] && tmpEBRFileName "$disk_number" "$part_number" + restorePartition "$restorepart" "$disk_number" "$imagePath" "$mc" + [[ $imgType =~ [Nn] ]] && restoreEBR "$restorepart" "$tmpebrfilename" + [[ $imgType =~ [Nn] ]] && expandPartition "$restorepart" "$fixed_size_partitions" + [[ $osid == +([5-7]) && $imgType =~ [Nn] ]] && fixWin7boot "$restorepart" + done + restoreparts="" + echo " * Resetting UUIDs for $disk" + debugPause + restoreUUIDInformation "$disk" "$mainuuidfilename" + echo " * Resettings swap systems" + debugPause + makeAllSwapSystems "$disk" "$disk_number" "$imagePath" "$imgPartitionType" + let disk_number+=1 + done +} diff --git a/draft/other-tools/fog/partition-funcs.sh b/draft/other-tools/fog/partition-funcs.sh new file mode 100644 index 0000000..8d77ec5 --- /dev/null +++ b/draft/other-tools/fog/partition-funcs.sh @@ -0,0 +1,811 @@ +#!/bin/bash +# +# These functions are for dealing with resizing of partitions. +# They currently work for MBR and Extended partition tables. +# THE DO NOT WORK FOR GPT. +# It is assumed that at most 1 extended partition will exist, +# with any number of logical partitions. +# Requires the sfdisk tool. +# Assumes that sfdisk's "unit: sectors" means 512 byte sectors. +# +# $1 is the name of the disk drive +# $2 is name of file to save to. +saveSfdiskPartitions() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to save to (${FUNCNAME[0]})\n Args Passed: $*" + sfdisk -d $disk 2>/dev/null > $file + [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})" +} +# $1 is the name of the disk drive +# $2 is name of file to save to. +saveUUIDInformation() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to save to passed (${FUNCNAME[0]})\n Args Passed: $*" + local hasgpt=0 + hasGPT "$disk" + [[ $hasgpt -eq 0 ]] && return + rm -f $file + touch $file + local diskuuid="" + local partuuid="" + local partfsuuid="" + local parts="" + local part="" + local part_number="" + local strtoadd="" + local is_swap=0 + getDiskUUID "$disk" + echo "$disk $diskuuid" >> $file + getPartitions "$disk" + for part in $parts; do + getPartitionNumber "$part" + partitionIsSwap "$part" + [[ $is_swap -gt 0 ]] && continue + getPartUUID "$part" + getPartFSUUID "$part" + [[ -n $partfsuuid ]] && strtoadd="$part $part_number:$partfsuuid" + [[ -n $partuuid ]] && strtoadd="$strtoadd $part_number:$partuuid" + echo "$strtoadd" >> $file + strtoadd="" + done +} +# $1 is the name of the disk drive +# $2 is name of file to restore from +restoreUUIDInformation() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to load from passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ ! -r $file ]] && return + local diskuuid="" + local partuuid="" + local escape_disk=$(escapeItem $disk) + local escape_part="" + local is_swap=0 + diskuuid=$(awk "/^$escape_disk\ /{print \$2}" $file) + [[ -n $diskuuid ]] && sgdisk -U $diskuuid $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to set disk guid (sgdisk -U) (${FUNCNAME[0]})\n Args Passed: $*" + getPartitions "$disk" + for part in $parts; do + partitionIsSwap "$part" + [[ $is_swap -gt 0 ]] && continue + escape_part=$(escapeItem $part) + local oIFS=$IFS + local IFS=$'\n' + read partuuid parttype <<< $(awk "/^$escape_part\ /{printf(\"%s\n%s\",\$2,\$3)}" $file) + IFS=$oIFS + [[ -n $parttype ]] && sgdisk -t $parttype $disk >/dev/null 2>&1 || true + [[ ! $? -eq 0 ]] && handleError " Failed to set partition type (sgdisk -t) (${FUNCNAME[0]})\n Args Passed: $*" + [[ -n $partuuid ]] && sgdisk -u $partuuid $disk >/dev/null 2>&1 || true + [[ ! $? -eq 0 ]] && handleError "Failed to set partition guid (sgdisk -u) (${FUNCNAME[0]})\n Args Passed: $*" + done +} +# $1 is the name of the disk drive +# $2 is name of file to load from. +applySfdiskPartitions() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdisk $disk < $file >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})" +} +# $1 is the name of the disk drive +# $2 is the name of file to load from. +applySgdiskPartitions() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*" + local escape_disk=$(escapeItem $disk) + local diskguid=$(awk -F: "/^$escape_disk:/{print \$3}" $file) + sgdisk -Z $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partitions (sgdisk -Z) (${FUNCNAME[0]})\n Args Passed: $*" + sgdisk -U $diskguid $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partitions (sgdisk -U) (${FUNCNAME[0]})\n Args Passed: $*" + local parts="" + local part="" + local part_number="" + local escape_part="" + local partstart="" + local partend="" + local parttype="" + local partcode="" + local partname="" + local awk_part_vars="" + getPartitions "$disk" + for part in $parts; do + escape_part=$(escapeItem $part) + getParititionNumber "$part" + awk_part_vars=$(awk -F: "/^$escape_part:/{printf(\"%d %d %d %d\",\$3,\$4,\$5,\$6)}" $file) + read partcode partstart partend partname <<< $awk_part_vars + parttype=$(awk -F: "/^part:$part_number:/{print \$5}" $file) + sgdisk -n $part_number:$partstart:$partend $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -n) (${FUNCNAME[0]})\n Args Passed: $*" + sgdisk -c $part_number:$partname $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -c) (${FUNCNAME[0]})\n Args Passed: $*" + sgdisk -t $part_number:$parttype $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -t) (${FUNCNAME[0]})\n Args Passed: $*" + sgdisk -u $part_number:$partcode $disk >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -u) (${FUNCNAME[0]})\n Args Passed: $*" + done +} +# $1 is the name of the disk drive +# $2 is name of file to load from. +restoreSfdiskPartitions() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*" + applySfdiskPartitions "$disk" "$file" + fdisk $disk < /usr/share/fog/lib/EOFRESTOREPART >/dev/null 2>&1 + [[ ! $? -eq 0 ]] && majorDebugEcho "fdisk failed in (${FUNCNAME[0]})" +} +# $1 is the name of the disk drive +# $2 is name of file to restore from. +restoreSgdiskPartitions() { + local disk="$1" + local file="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to restore from (${FUNCNAME[0]})\n Args Passed: $*" + applySgdiskPartitions "$disk" "$file" +} +# $1 is the name of the disk drive +hasExtendedPartition() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + sfdisk -d $disk 2>/dev/null | egrep '(Id|type)=\ *[5f]' | wc -l + [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})" +} +# $1 is the name of the partition device (e.g. /dev/sda3) +partitionHasEBR() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local part_number=0 + local disk="" + local parttype="" + getDiskFromPartition "$part" + getPartitionNumber "$part" + getPartType "$part" + hasEBR=0 + [[ $part_number -ge 5 ]] && hasEBR=1 + [[ $parttype == +(0x5|0xf) ]] && hasEBR=1 +} +# $1 is the name of the partition device (e.g. /dev/sda3) +# $2 is the name of the file to save to (e.g. /net/dev/foo/d1p4.ebr) +saveEBR() { + local part="$1" + local file="$2" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + getDiskFromPartition "$part" + local table_type="" + getPartitionTableType "$disk" + [[ $table_type != MBR ]] && return + local hasEBR=0 + partitionHasEBR "$part" + [[ ! $hasEBR -gt 0 ]] && return + dots "Saving EBR for ($part)" + dd if=$part of=$file bs=512 count=1 >/dev/null 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError "Could not backup EBR (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac +} +# $1 = DriveName (e.g. /dev/sdb) +# $2 = DriveNumber (e.g. 1) +# $3 = ImagePath (e.g. /net/foo) +saveAllEBRs() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local parts="" + local part="" + local part_number=0 + local ebrfilename="" + getPartitions "$disk" + for part in $parts; do + getPartitionNumber "$part" + EBRFileName "$imagePath" "$disk_number" "$part_number" + saveEBR "$part" "$ebrfilename" + done +} +# $1 is the name of the partition device (e.g. /dev/sda3) +# $2 is the name of the file to restore from (e.g. /net/foo/d1p4.ebr) +restoreEBR() { + local part="$1" + local file="$2" + [[ -z $part ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to restore from passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + local table_type="" + getDiskFromPartition "$part" + getPartitionTableType "$disk" + [[ $table_type != MBR ]] && return + local hasEBR=0 + partitionHasEBR "$part" + [[ ! $hasEBR -gt 0 ]] && return + [[ ! -e $file ]] && return + dots "Restoring EBR for ($part)" + dd of=$part if=$file bs=512 count=1 >/dev/null 2>&1 + case $? in + 0) + echo "Done" + debugPause + ;; + *) + echo "Failed" + debugPause + handleError "Could not reload EBR data (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac +} +# $1 = DriveName (e.g. /dev/sdb) +# $2 = DriveNumber (e.g. 1) +# $3 = ImagePath (e.g. /net/foo) +# $4 = ImagePartitionType (e.g. all, mbr, 1, 2, 3, etc.) +restoreAllEBRs() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + local imgPartitionType="$4" + local ebffilename="" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imgPartitionType ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*" + local parts="" + local part="" + local part_number=0 + local ebrfilename="" + getPartitions "$disk" + for part in $parts; do + getPartitionNumber "$part" + [[ $imgPartitionType != all && $imgPartitionType != $part_number ]] && continue + EBRFileName "$imagePath" "$disk_number" "$part_number" + restoreEBR "$part" "$ebrfilename" + done + runPartprobe "$disk" +} +# $1 is the name of the partition device (e.g. /dev/sda3) +partitionIsSwap() { + local part="$1" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + local fstype="" + fsTypeSetting "$part" + is_swap=0 + [[ $fstype == swap ]] && is_swap=1 +} +# $1 is the location of the file to store uuids in +# $2 is the partition device name +saveSwapUUID() { + local file="$1" + local part="$2" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*" + local is_swap=0 + partitionIsSwap "$part" + [[ $is_swap -eq 0 ]] && return + local uuid=$(blkid -s UUID $2 | cut -d\" -f2) + [[ -z $uuid ]] && return + echo " * Saving UUID ($uuid) for ($part)" + echo "$part $uuid" >> $file +} +# Linux swap partition strategy: +# +# Upload: +# +# In "n" mode, the empty swapUUIDFileName is created first. Then as each +# partition is saved, if it is swap then saveSwapUUID is called. +# In "mps" and "mpa" mode, savePartition is called for each partition. +# savePartition then calles saveSwapUUID if the partition is swap. +# +# When uploading an image, the swapUUIDFileName (e.g. /images/foo/d1.original.swapuuids) +# is created. For $imgPartitionType == "all", all swap partition UUIDs are saved. +# For $imgPartitionType == "$partnum", the partition's UUID is saved, if it is a swap partition. +# For all others, the swapUUIDFileName will not exist, or will be empty. +# +# +# Download: +# +# When downloading an image, makeAllSwapSystems will be called. +# In "n" mode this is done for those images without special configurations, +# after normal partition restoration. +# In "mps" mode this is always done +# In "mpa" mode this is always done, for all disks. +# makeAllSwapSystems will determine using +# $imagePartitionType == "all" or == "$partnum" whether to +# process the swapUUIDFileName contents. For each matching partition, +# mkswap is used, and the UUID is set appropriately. +# +# Relevant functions: +# swapUUIDFileName ImagePath DriveNumber +# echos the standardized name for the UUID filename +# partitionIsSwap PartitionName +# echos 1 or 0 if fsTypeSetting says partition is or is not a swap partition. +# makeSwapSystem SwapUUIDFileName PartitionName +# if it finds partition in UUID file, then calls mkswap +# makeAllSwapSystems DriveName DriveNumber ImagePath ImagePartitionType +# checks ImagePartitionType for a match before calling makeSwapSystem +# saveSwapUUID SwapUUIDFileName PartitionName +# checks if paritionIsSwap, if so, obtains UUID and saves it +# saveAllSwapUUIDs DriveName DriveNumber ImagePath +# checks all partitions if partitionIsSwap, calles saveSwapUUID +# savePartition: +# calls saveSwapUUID for swap partitions +# +# +# $1 = DriveName (e.g. /dev/sdb) +# $2 = DriveNumber (e.g. 1) +# $3 = ImagePath (e.g. /net/foo) +saveAllSwapUUIDs() { + local disk="$1" + local disk_number="$2" + local imagePath="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local swapuuidfilename="" + swapUUIDFileName "$imagePath" "$disk_number" + local parts="" + local part="" + local is_swap=0 + getPartitions "$disk" + for part in $parts; do + partitionIsSwap "$part" + [[ $is_swap -eq 0 ]] && continue + saveSwapUUID "$swapuuidfilename" "$part" + done +} +# $1 is the location of the file uuids are stored in +# $2 is the partition device name +makeSwapSystem() { + local file="$1" + local part="$2" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file passed (${FUNCNAME[0]})\n Args Passed: $*" + local uuid="" + local option="" + local disk="" + getDiskFromPartition "$part" + local parttype=0 + local hasgpt="" + local escape_part=$(escapeItem $part) + hasGPT "$disk" + case $hasgpt in + 1) + uuid=$(awk "/^$escape_part/{print \$2}" $file) + [[ -n $uuid ]] && parttype=82 + ;; + 0) + parttype=$(sfdisk -d $disk 2>/dev/null | awk -F[,=] "/^$escape_part/{print \$6}") + ;; + esac + [[ ! $parttype -eq 82 ]] && return + [[ -n $uuid ]] && option="-U $uuid" + dots "Restoring swap partition" + mkswap $option $part >/dev/null 2>&1 + case $? in + 0) + echo "Done" + ;; + *) + echo "Failed" + debugPause + handleError "Could not create swap on $part (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + debugPause +} +# $1 is the partition device (e.g. /dev/sda1) +# $2 is the new desired size in 1024 (1k) blocks +# $3 is the image path (e.g. /net/dev/foo) +resizeSfdiskPartition() { + local part="$1" + local size="$2" + local imagePath="$3" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $size ]] && handleError "No desired size passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + getDiskFromPartition "$part" + local tmp_file="/tmp/sfdisk.$$" + local tmp_file2="/tmp/sfdisk2.$$" + saveSfdiskPartitions "$disk" "$tmp_file" + processSfdisk "$tmp_file" resize "$part" "$size" > "$tmp_file2" + if [[ $ismajordebug -gt 0 ]]; then + majorDebugEcho "Trying to fill the disk with these partitions:" + cat $tmp_file2 + majorDebugPause + fi + applySfdiskPartitions "$disk" "$tmp_file2" + local sfdiskminimumpartitionfilename="" + sfdiskMinimumPartitionFileName "$imagePath" 1 + saveSfdiskPartitions "$disk" "$imagePath" +} +# $1 is the disk device (e.g. /dev/sda) +# $2 is the name of the original sfdisk -d output file used as a template +# $3 is the : separated list of fixed size partitions (e.g. 1:2) +# swap partitions are automatically added. Empty string is +# ok. +fillSfdiskWithPartitions() { + local disk="$1" + local file="$2" + local fixed="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $file ]] && handleError "No file to use passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk_size=$(blockdev --getsize64 $disk | awk '{printf("%d\n",$1/1024);}') + local tmp_file2="/tmp/sfdisk2.$$" + processSfdisk "$file" filldisk "$disk" "$disk_size" "$fixed" > "$tmp_file2" + if [[ $ismajordebug -gt 0 ]]; then + majorDebugEcho "Trying to fill with the disk with these partititions:" + cat $tmp_file2 + majorDebugPause + fi + [[ $? -eq 0 ]] && applySfdiskPartitions "$disk" "$tmp_file2" + runPartprobe "$disk" + rm -f $tmp_file2 + majorDebugEcho "Applied the preceding table." + majorDebugShowCurrentPartitionTable "$disk" 1 + majorDebugPause +} +# +# processSfdisk() processes the output of sfdisk -d +# and creates a new sfdisk -d like output, applying +# the requested action. Read below to see the actions +# +# $1 the name of a file that is the output of sfdisk -d +# $2 is the action "resize|other?" +# $3 is the first parameter +# $4 is the second parameter +# ... +# +# actions: +# processSfdisk foo.sfdisk resize /dev/sda1 100000 +# foo.sfdisk = sfdisk -d output +# resize = action +# /dev/sda1 = partition to modify +# 100000 = 1024 byte blocks size to make it +# output: new sfdisk -d like output +# +# processSfdisk foo.sfdisk move /dev/sda1 100000 +# foo.sfdisk = sfdisk -d output +# move = action +# /dev/sda1 = partition to modify +# 100000 = 1024 byte blocks size to move it to +# output: new sfdisk -d like output +# +# processSfdisk foo.sfdisk filldisk /dev/sda 100000 1:3:6 +# foo.sfdisk = sfdisk -d output +# filldisk = action +# /dev/sda = disk to modify +# 100000 = 1024 byte blocks size of disk +# 1:3:6 = partition numbers that are fixed in size, : separated +# output: new sfdisk -d like output +# +# example file data +# /dev/sda1 : start= 2048, size= 204800, Id= 7, bootable +# /dev/sda2 : start= 206848, size= 50573312, Id= 7 +# /dev/sda3 : start= 50780160, size= 2048, Id=83 +# /dev/sda4 : start= 50784254, size= 16322562, Id= 5 +# /dev/sda5 : start= 50784256, size= 7811072, Id=83 +# /dev/sda6 : start= 58597376, size= 8509440, Id=82 +# +processSfdisk() { + local data="$1" + local action="$2" + local target="$3" + local size="$4" + local fixed="$5" + [[ -z $data ]] && handleError "No data passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $action ]] && handleError "No action passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $target ]] && handleError "Device (disk or partition) not passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $size ]] && handleError "No desired size passed (${FUNCNAME[0]})\n Args Passed: $*" + local minstart=$(awk -F'[ ,]+' '/start/{if ($4) print $4}' $data | sort -n | head -1) + local chunksize="" + getPartBlockSize "$disk" "chunksize" + case $osid in + [1-2]) + [[ -z $minstart ]] && chunksize=512 + [[ -z $minstart ]] && minstart=63 + ;; + esac + local awkArgs="-v CHUNK_SIZE=$chunksize -v MIN_START=$minstart" + awkArgs="$awkArgs -v action=$action -v target=$target -v sizePos=$size" + [[ -n $fixed ]] && awkArgs="$awkArgs -v fixedList=$fixed" + # process with external awk script + /usr/share/fog/lib/procsfdisk.awk $awkArgs $data +} +# +# GPT Functions below +# +# $1 : device name of drive +getPartitionTableType() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + local mbr=$(yes '' | gdisk -l $disk | awk '/^\ *MBR:/{print $2}') + local gpt=$(yes '' | gdisk -l $disk | awk '/^\ *GPT:/{print $2}') + local type="" + local mbrtype="" + local gpttype="" + case $mbr in + present|MBR) + mbrtype="MBR" + ;; + hybrid) + mbrtype="HYBRID" + ;; + protective|not) + mbrtype="" + ;; + esac + case $gpt in + present|damaged) + gpttype="GPT" + ;; + not) + gpttype="" + ;; + esac + [[ -z $gpttype && -z $mbrtype ]] && handleError "Cannot determine partition type (${FUNCNAME[0]})\n Args Passed: $*" + [[ -n $gpttype && -n $mbrtype ]] && table_type="$gpttype-$mbrtype" + [[ -n $gpttype && -z $mbrtype ]] && table_type="$gpttype" + [[ -z $gpttype && -n $mbrtype ]] && table_type="$mbrtype" +} +# +# Detect the desired partition table type, +# using the available files in imagePath, don't rely +# on the actual disk. +# +# Assumes GPT or MBR. Uses first 8 bytes of second block +# which should hold "EFI PART". (https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_table_header_.28LBA_1.29) +# +# $1 : imagePath (e.g. /images/foo) +# $2 : disk number (e.g. 1) +getDesiredPartitionTableType() { + local imagePath="$1" + local disk_number="$2" + [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + table_type="MBR" + local mbrfilename="" + MBRFileName "$imagePath" "$disk_number" "mbrfilename" + [[ ! -r $mbrfilename ]] && return + local tmpfile="/tmp/gptsig" + dd skip=512 bs=1 if=$mbrfilename of=$tmpfile count=8 >/dev/null 2>&1 + touch $tmpfile + local gptsig=$(cat $tmpfile) + [[ $gptsig == "EFI PART" ]] && table_type="GPT" +} +# $1 : device name of drive +hasHybridMBR() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + local mbr=$(gdisk -l $disk | awk '/^\ *MBR:/{print $2}') + [[ $mbr == hybrid ]] && echo 1 || echo 0 +} +# $1 : device name of drive +hasGPT() { + local disk="$1" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + local gpt=$(gdisk -l $disk | awk -F'[(: )]' '/GPT:/ {print $5}') + [[ $gpt == present ]] && hasgpt=1 + [[ $gpt == not ]] && hasgpt=0 +} +# +# Detect the partition table type, then call the correct +# resizePartition function +# +# $1 is the partition device (e.g. /dev/sda1) +# $2 is the new desired size in 1024 (1k) blocks +# $3 is the image path (e.g. /net/dev/foo) +resizePartition() { + local part="$1" + local size="$2" + local imagePath="$3" + [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $size ]] && handleError "No size passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + local disk="" + local table_type="" + getDiskFromPartition "$part" + getPartitionTableType "$disk" + case $table_type in + MBR|GPT) + local sfdiskoriginalpartitionfilename="" + local sfdisklegacyoriginalpartitionfilename="" + resizeSfdiskPartition "$part" "$size" "$imagePath" + ;; + *) + handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + # make sure kernel knows about the changes + runPartprobe "$disk" +} +# +# Detect the partition table type, then save all relevant +# partition information +# +# $1 : device name of the drive +# $2 : imagePath +# $3 : disk number +saveOriginalPartitions() { + local disk="$1" + local imagePath="$2" + local disk_number="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + local table_type="" + getPartitionTableType "$disk" + case $table_type in + MBR|GPT) + local sfdiskoriginalpartitionfilename="" + sfdiskOriginalPartitionFileName "$imagePath" "$disk_number" + saveSfdiskPartitions "$disk" "$sfdiskoriginalpartitionfilename" + ;; + GPT-MBR) + echo "Failed" + debugPause + runFixparts "$disk" + dots "Retrying to save partition table" + saveOriginalPartitions "$disk" "$imagePath" "$disk_number" + ;; + *) + echo "Failed" + debugPause + handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + runPartprobe "$disk" +} +# +# Detect the partition table type, then restore partition +# sizes, using saved partition information +# +# $1 : device name of the drive +# $2 : imagePath +# $3 : disk number +restoreOriginalPartitions() { + local disk="$1" + local imagePath="$2" + local disk_number="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + local table_type="" + getPartitionTableType "$disk" + case $table_type in + MBR|GPT) + local sfdiskoriginalpartitionfilename="" + local sfdisklegacyoriginalpartitionfilename="" + local sgdiskoriginalpartitionfilename="" + local cmdtorun='restoreSfdiskPartitions' + sfdiskOriginalPartitionFileName "$imagePath" "$disk_number" + sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number" + sgdiskOriginalPartitionFileName "$imagePath" "$disk_number" + local filename="$sfdiskoriginalpartitionfilename" + [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename" + [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename" && cmdtorun='restoreSgdiskPartitions' + [[ ! -r $filename ]] && handleError "Failed to find a restore file (${FUNCNAME[0]})\n Args Passed: $*" + $cmdtorun "$disk" "$filename" + ;; + *) + handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + # make sure kernel knows about the changes + runPartprobe "$disk" +} +# +# Detect the partition table type, the fill the disk with +# the partitions, using the correct routine. +# +# $1 : the disk device (e.g. /dev/sda) +# $2 : imagePath (e.g. /images/foo) +# $3 : disk number (e.g. 1) +fillDiskWithPartitions() { + local disk="$1" + local imagePath="$2" + local disk_number="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + local fixed_size_file="" + fixedSizePartitionsFileName "$imagePath" "$disk_number" + [[ -r $fixed_size_file ]] && fixed_size_partitions=$(cat $fixed_size_file) + local table_type="" + getDesiredPartitionTableType "$imagePath" "$disk_number" + local sfdiskoriginalpartitionfilename="" + local sfdisklegacyoriginalpartitionfilename="" + local sgdiskoriginalpartitionfilename="" + case $table_type in + MBR|GPT) + sfdiskOriginalPartitionFileName "$imagePath" "$disk_number" + sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number" + sgdiskOriginalPartitionFileName "$imagePath" "$disk_number" + local filename="$sfdiskoriginalpartitionfilename" + local cmdtorun='fillSfdiskWithPartitions' + [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename" + [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename" + [[ $filename == $sgdiskoriginalpartitionfilename ]] && cmdtorun='fillSgdiskWithPartitions' + [[ ! -r $filename ]] && handleError "Failed to find a restore file (${FUNCNAME[0]})\n Args Passed: $*" + $cmdtorun "$disk" "$filename" "$fixed_size_partitions" + ;; + *) + echo "Failed" + debugPause + handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*" + ;; + esac + # make sure kernel knows about the changes + runPartprobe "$disk" +} +# +# Check if it will be ok to call fillDiskWithPartitions +# +# $1 : the disk device (e.g. /dev/sda) +# $2 : imagePath (e.g. /images/foo) +# $3 : disk number (e.g. 1) +fillDiskWithPartitionsIsOK() { + local disk="$1" + local imagePath="$2" + local disk_number="$3" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + local table_type="" + getDesiredPartitionTableType "$imagePath" "$disk_number" + local filename="" + local sfdiskoriginalpartitionfilename="" + local sfdisklegacyoriginalpartitionfilename="" + local sgdiskoriginalpartitionfilename="" + do_fill=1 + case $table_type in + MBR|GPT) + sfdiskOriginalPartitionFileName "$imagePath" "$disk_number" + sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number" + sgdiskOriginalPartitionFileName "$imagePath" "$disk_number" + filename="$sfdiskoriginalpartitionfilename" + [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename" + [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename" + [[ ! -r $filename ]] && do_fill=0 + ;; + esac +} +# +# Show the current partition table +# +# $1 : the disk device (e.g. /dev/sda) +# $2 : disk number (e.g. 1) +majorDebugShowCurrentPartitionTable() { + [[ $ismajordebug -le 0 ]] && return + local disk="$1" + local disk_number="$2" + [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*" + [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*" + local table_type="" + getDesiredPartitionTableType "$imagePath" "$disk_number" + echo "Current partition table:" + case $table_type in + MBR|GPT) + sfdisk -d $disk + ;; + esac +} diff --git a/draft/other-tools/fog/procsfdisk.awk b/draft/other-tools/fog/procsfdisk.awk new file mode 100644 index 0000000..ac18749 --- /dev/null +++ b/draft/other-tools/fog/procsfdisk.awk @@ -0,0 +1,361 @@ +#!/usr/bin/awk -f + +#$data is the filename of the output of sfdisk -d + +#cat $data | awk -F, '\ + +# For readability, function parameters are on the first line. Locally scoped +# variables are on the following lines. + +function display_output(partition_names, partitions, \ + pName) { + if (!unit) { + unit = "sectors"; + } + if (!label) { + type = "Id="; + } else { + type = "type="; + } + if (label && labelid && device) { + printf("label: %s\n", label); + printf("label-id: %s\n", labelid); + printf("device: %s\n", device); + } + printf("unit: %s\n\n", unit); + for(pName in partition_names) { + printf("%s : start=%10d, size=%10d, %s%2s", partitions[pName, "device"], partitions[pName, "start"], partitions[pName, "size"], + type, partitions[pName, "type"]); + if(label == "dos") { + if(partitions[pName, "flags"] != "") { + printf("%s", partitions[pName, "flags"]); + } + } else if (label == "gpt") { + if(partitions[pName, "uuid"] != "") { + printf(", uuid=%s", partitions[pName, "uuid"]); + } + if(partitions[pName, "name"] != "") { + printf(", name=%s", partitions[pName, "name"]); + } + if(partitions[pName, "attrs"] != "") { + printf(", attrs=%s", partitions[pName, "attrs"]); + } + } else { + if(partitions[pName, "flags"] != "") { + printf("%s", partitions[pName, "flags"]); + } + } + printf("\n"); + } +} + +function check_overlap(partition_names, partitions, new_part_name, new_start, new_size, \ + extended_margin, new_type, new_part_number, pName, p_type, p_start, p_size, p_part_number) { + extended_margin = 2; + new_type = partitions[new_part_name, "type"]; + new_start = new_start + 0; + new_size = new_size + 0; + new_part_number = partitions[new_part_name, "number"] + 0; + for(pName in partition_names) { + p_type = partitions[pName, "type"]; + p_start = partitions[pName, "start"] + 0; + p_size = partitions[pName, "size"] + 0; + p_part_number = partitions[pName, "number"] + 0; + # no overlap with self + if(new_part_name == pName) { continue; } + # ignore empty partitions + if(p_size == 0) { continue; } + # extended partitions must overlap logical partitions, but leave room for the extended partition table + if((p_type == "5" || p_type == "f") && (new_part_number >= 5)) { + # new_start is outside of [p_start+margin, p_start + p_size) OR + # new_start + new_size is outside of (p_start+margin, p_start + p_size] + if((new_start < p_start + extended_margin || new_start >= p_start + p_size) || (new_start + new_size <= p_start + extended_margin || new_start + new_size > p_start + p_size)) { + return 1; + } + } + # extended partitions must overlap logical partitions, but leave room for the extended partition table + else if((new_type == "5" || new_type == "f") && (p_part_number >= 5)) { + # logical partition must be contained in extended partition + # p_start is outside of [new_start+margin, new_start + new_size) OR + # p_start + p_size is outside of (new_start+margin, new_start + new_size] + if((p_start < new_start + extended_margin || p_start >= new_start + new_size) || (p_start + p_size <= new_start + extended_margin || p_start + p_size > new_start + new_size)) { + return 1; + } + } + # all other overlap possibilities + else { + # new_start is inside of [p_start, p_start + p_size) OR + # new_start + new_size is inside of (p_start, p_start + p_size] + if((new_start >= p_start && new_start < p_start + p_size) || (new_start + new_size > p_start && new_start + new_size <= p_start + p_size)) { + return 1; + } + # p_start is inside of [new_start, new_start + new_size) OR + # p_start + p_size is inside of (new_start, new_start + new_size] + if((p_start >= new_start && p_start < new_start + new_size) || (p_start + p_size > new_start && p_start + p_size <= new_start + new_size)) { + return 1; + } + } + } + return 0; +} + +function check_all_partitions(partition_names, partitions, \ + pName, p_start, p_size) { + for(pName in partition_names) { + p_start = partitions[pName, "start"] + 0; + p_size = partitions[pName, "size"] + 0; + if(check_overlap(partition_names, partitions, pName, p_start, p_size) != 0) { + printf("ERROR in new partition table, quitting.\n"); + printf("ERROR: %s has an overlap.\n", pName); + #exit(1); + } + } + printf("# Partition table is consistent.\n"); +} + +function resize_partition(partition_names, partitions, args, \ + pName, new_start, new_size) { + for(pName in partition_names) { + if(pName == target) { + if(unit == "sectors") { + new_start = partitions[pName, "start"]; + new_size = sizePos*2; + if(check_overlap(partition_names, partitions, target, new_start, new_size) == 0) { + partitions[target, "start"] = new_start; + partitions[target, "size"] = new_size; + } + } + } + } +} + +function move_partition(partition_names, partitions, args, \ + pName, new_start, new_size) { + for(pName in partition_names) { + if(pName == target) { + if(unit == "sectors") { + new_start = (sizePos*2); + new_start = new_start - new_start % CHUNK_SIZE; + if(new_start < MIN_START) { new_start = MIN_START; } + new_size = partitions[pName, "size"]; + if(check_overlap(partition_names, partitions, target, new_start, new_size) == 0) { + partitions[target, "start"] = new_start; + partitions[target, "size"] = new_size; + } + } + } + } +} + +function fill_disk(partition_names, partitions, args, \ + disk, disk_size, n, fixed_partitions, original_variable, \ + original_fixed, new_variable, new_fixed, new_logical, pName, \ + p_type, p_number, p_size, found, i, partition_starts, \ + ordered_starts, old_sorted_in, curr_start) { + # processSfdisk foo.sfdisk filldisk /dev/sda 100000 1:3:6 + # foo.sfdisk = sfdisk -d output + # filldisk = action + # /dev/sda = disk to modify + # 100000 = 1024 byte blocks size of disk + # 1:3:6 = partition numbers that are fixed in size, : separated + disk = target; + disk_size = sizePos*2; + # add swap partitions to the fixed list + for(pName in partition_names) { + p_type = partitions[pName, "type"]; + p_number = partitions[pName, "number"] + ""; + if(p_type == "82") { + fixedList = fixedList ":" p_number; + } + } + n = split(fixedList, fixed_partitions, ":"); + # + # Find the total fixed and variable space + # + original_variable = 0; + original_fixed = MIN_START; + for(pName in partition_names) { + p_type = partitions[pName, "type"]; + p_number = partitions[pName, "number"] + 0; + p_size = partitions[pName, "size"] + 0; + partition_starts[partitions[pName, "start"] + 0] = pName; + # skip extended partition, only count its logicals and the CHUNK for its partition table + if(p_type == "5" || p_type == "f") { + original_fixed += CHUNK_SIZE; + continue; + } + # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist) + if(p_number >= 5) { + original_fixed += CHUNK_SIZE; + } + if(p_size == 0) { fixed_partitions[pName] = p_number; }; + found = 0; for(i in fixed_partitions) { if(fixed_partitions[i] == p_number) { found = 1; } }; + if(found) { + original_fixed += partitions[pName, "size"]; + } else { + original_variable += partitions[pName, "size"]; + } + } + # + # Assign the new sizes to partitions + # + new_fixed = original_fixed; + new_variable = disk_size - original_fixed; + new_logical = 0; + for(pName in partition_names) { + p_type = partitions[pName, "type"]; + p_number = partitions[pName, "number"] + 0; + p_size = partitions[pName, "size"] + 0; + found = 0; + for(i in fixed_partitions) { + if(fixed_partitions[i] == p_number) { + found = 1; + } + }; + if(p_type == "5" || p_type == "f") { + partitions[pName, "newsize"] = CHUNK_SIZE; + partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE; + } else if(found) { + partitions[pName, "newsize"] = p_size; + partitions[pName, "size"] = partitions[pName, "newsize"]; + } else { + partitions[pName, "newsize"] = (new_variable*p_size/original_variable); + partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE; + } + if(p_number >= 5) { + # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist) + new_logical += partitions[pName, "size"] + CHUNK_SIZE; + } + } + # + # Assign the new size to the extended partition + # + for(pName in partition_names) { + p_type = partitions[pName, "type"]; + p_number = partitions[pName, "number"] + 0; + p_size = partitions[pName, "size"] + 0; + if(p_type == "5" || p_type == "f") { + partitions[pName, "newsize"] += new_logical; + partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE; + } + } + # + # Assign the new start positions + # + asort(partition_starts, ordered_starts, "@ind_num_asc"); + old_sorted_in = PROCINFO["sorted_in"]; + PROCINFO["sorted_in"] = "@ind_num_asc"; + curr_start = MIN_START; + for(i in ordered_starts) { + pName = ordered_starts[i]; + p_type = partitions[pName, "type"]; + p_number = partitions[pName, "number"] + 0; + p_size = partitions[pName, "size"] + 0; + p_start = partitions[pName, "start"] + 0; + for (j in fixed_partitions) { + if (fixed_partitions[j] == p_number) { + curr_start = p_start; + } + } + if(p_size > 0) { + partitions[pName, "start"] = curr_start; + } + if(p_type == "5" || p_type == "f") { + curr_start += CHUNK_SIZE; + } else { + curr_start += p_size; + } + # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist) + if(p_number >= 5) { + curr_start += CHUNK_SIZE; + } + } + PROCINFO["sorted_in"] = old_sorted_in; + check_all_partitions(partition_names, partitions); +} + +BEGIN{ + #Arguments - Use "-v var=val" when calling this script + #CHUNK_SIZE; + #MIN_START; + #action; + #target; + #sizePos; + #fixedList; + label = ""; + unit = ""; + partitions[0] = ""; + partition_names[0] = ""; +} + +/^label:/{ label = $2 } +/^label-id:/{ labelid = $2 } +/^device:/{ device = $2 } +/^unit:/{ unit = $2; } + +/start=/{ + # Get Partition Name + part_name=$1 + partitions[part_name, "device"] = part_name + partition_names[part_name] = part_name + + # Isolate Partition Number + # The regex can handle devices like mmcblk0p3 + part_number = gensub(/^[^0-9]*[0-9]*[^0-9]+/, "", 1, part_name) + partitions[part_name, "number"] = part_number + + # Separate attributes + split($0, fields, ",") + + # Get start value + gsub(/.*start= */, "", fields[1]) + partitions[part_name, "start"] = fields[1] + # Get size value + gsub(/.*size= */, "", fields[2]) + partitions[part_name, "size"] = fields[2] + # Get type/id value + gsub(/.*(type|Id)= */, "", fields[3]) + partitions[part_name, "type"] = fields[3] + + if ( label == "dos" ) + { + split($0, typeList, "type=") + part_flags = gensub(/^[^\,$]*/, "",1,typeList[2]) + partitions[part_name, "flags"] = part_flags; + } + # GPT elements + else if ( label == "gpt" ) + { + # Get uuid value + gsub(/.*uuid= */, "", fields[4]) + partitions[part_name, "uuid"] = fields[4] + # Get name value + gsub(/.*name= */, "", fields[5]) + partitions[part_name, "name"] = fields[5] + # Get attrs value + if (fields[6]) + { + gsub(/.*attrs= */, "", fields[6]) + partitions[part_name, "attrs"] = fields[6] + } + } + else + { + split($0, typeList, "Id=") + part_flags = gensub(/^[^\,$]*/, "",1,typeList[2]) + partitions[part_name, "flags"] = part_flags; + } +} + +END{ + delete partitions[0]; + delete partition_names[0]; + if(action == "resize") { + resize_partition(partition_names, partitions, args); + } else if(action == "move") { + move_partition(partition_names, partitions, args); + } else if(action == "filldisk") { + fill_disk(partition_names, partitions, args); + } + display_output(partition_names, partitions); +} -- cgit v1.2.3