Disk Information Retrieval.

Document writer <olivier.nicolas@insa-lyon.fr>
v1.0, 2022-11-24

Description.

Description of the process to retrieve the disk information that will be used when either creating (or flashing) an image; mainly, the last sector and the size of the image.

For that we extract the information from the output of sudo fdisk -l /dev/…​

fdisk
get_disk_info.sh
#!/bin/bash

# $1 is the device/image
# for example: /dev/sdb

get_disk_info ()
{
  sudo fdisk -l $1 > fdisk.txt

  # Line containing the word Device
  # Example:
  #         Device        Start        End   Sectors   Size Type
  Device_Line_Number=$(grep -n "^Device" fdisk.txt | tr ":" "\n"|head -n 1)
  Line_Count=$(cat fdisk.txt|wc -l)
  Partition_Count=$(expr $((Line_Count)) - $((Device_Line_Number)))

  Start_First_Char_Position=$(grep "^Device" fdisk.txt | grep -b -o Start | cut -d ":" -f1)
  Last_Sector_First_Char_Position=$(expr $((Start_First_Char_Position)) + 6)
  End_First_Char_Position=$(grep "^Device" fdisk.txt | grep -b -o End | cut -d ":" -f1)
  Last_Sector_Last_Char_Position=$(expr $((End_First_Char_Position)) + 3)

  Last_Sector=$(tail -n $Partition_Count fdisk.txt | cut -c$Last_Sector_First_Char_Position-$Last_Sector_Last_Char_Position | sort -n | tail -n 1)
  Last_Partition_Line_Number=$(tail -n $Partition_Count fdisk.txt | grep -n $Last_Sector | cut -d ":" -f1)

  # Get, out of the last *Last_Part__Line_Number lines* of the *Partition_Count* lines, the last line;
  # Which will be the line containing $END
  # Then get the first "word"; that will be the partition containing the word $END, aka the last partition
  Last_Partition=$(tail -n $Partition_Count fdisk.txt | head -n $Last_Partition_Line_Number | tail -n 1 | cut -d " " -f1)

  Last_Partition_Number=$(echo $Last_Partition | grep -Eo '[[:alpha:]]+|[0-9]+' | tail -n 1)

  Sector_Size=$(grep "Sector size" fdisk.txt | awk '{print $(NF - 4)}')
  Image_Size=$(( (($Last_Sector + 1)*$Sector_Size) / (1024*1024) ))

  rm fdisk.txt
}

Example:

$ echo $Image_Size
2950
This is the size of the image to be flashed, in MiB.
We would use it as such, for example:
$ sudo dd if=/dev/sdb of=/mnt/dest.img bs=1MiB count=$Image_Size conv=fsync

Examples:

A few example results of the following script:

getDriveUsefulSize.sh
#!/bin/bash

# $1 is the device/image

. ./get_disk_info.sh

get_disk_info $1

sudo fdisk -l $1
echo
echo Last partition is $Last_Partition, Partition \#$Last_Partition_Number
echo  It ends at sector $Last_Sector
echo
echo The size of the image to flash is: $Image_Size MiB
Device    Boot Start     End Sectors  Size Id Type
/dev/sdb1 *        0 6041599 6041600  2,9G  0 Empty
/dev/sdb2       5268   15283   10016  4,9M ef EFI (FAT-12/16/32)

Result:
Last partition is /dev/sdb1, Partition #1
It ends at sector 6041599
The size of the image to flash is: 2950 MiB
Device    Boot  Start     End Sectors  Size Id Type
/dev/sdb1        8192  532479  524288  256M  c W95 FAT32 (LBA)
/dev/sdb2      532480 3612671 3080192  1,5G 83 Linux

Result:
Last partition is /dev/sdb2, Partition #2
It ends at sector 3612671
The size of the image to flash is: 1764 MiB
Device        Start        End   Sectors   Size Type
/dev/sda1      2048    1050623   1048576   512M EFI System
/dev/sda2   1050624   33050623  32000000  15,3G Linux swap
/dev/sda3  33050624   97050623  64000000  30,5G Linux filesystem
/dev/sda4  97050624 1000214527 903163904 430,7G Linux filesystem

Result:
Last partition is /dev/sda4, Partition #4
It ends at sector 1000214527
The size of the image to flash is:  488386 MiB


This may need improvement in a case like the following depending on if we want the answer to be "1" or "p1".

  • device = /dev/mmcblk0

  • partition = /dev/mmcblk0p1

We could then use code like:

  str="/dev/mmcblk0p1"
  delimiter="/dev/mmcblk0"
  s=$str$delimiter
  array=();
  while [[ $s ]];
     do
       array+=( "${s%%"$delimiter"*}" );
       s=${s#*"$delimiter"};
     done;
  declare -p array
  echo ${array[1]}

returns p1