I need to write a 5MB block of data obtained from /dev/urandom to a partition, at a specific location in the partition. I then need to check that the write executed correctly. I was previously successfully doing this in C , but now I would like to implement it in a bash script.
My C code consisted of:
- create 10MB array of data populated from /dev/urandom (RANDOM_ARRAY)
- open partition with open()
- use lseek() to navigate to desired position in partition
- use write() to write the array into the partition
- close and reopen partition, use lseek to navigate back to desired position
- use read() to read 5MB at this position and populate another array with this data (WRITTEN_ARRAY)
- compare each element in (RANDOM_ARRAY) with (WRITTEN_ARRAY)
Im not experienced with writing bash scripts but this is what I've got so far, although it doesn't seem to work:
random_data="$(cat /dev/urandom | head -c<5MB>)"
printf $random_data | dd of=<partition_path> bs=1 seek=<position_in_partition> count=<5MB>
file_data=$(dd if=<partition_path> bs=1 skip=<position_in_partition> count=<5MB>)
if [ "$random_data" == "$file_data" ]
then
echo "data write successful"
fi
Thanks to the helpful commenters my script now looks something like this:
# get 10MB random data
head -c<10MB> /dev/urandom > random.bin
# write 10MB random data to partition
dd if=random.bin of=<partition_location>
# copy the written data
dd if=<partition_location> count=<10MB/512 bytes> of=newdata.bin
# compare
cmp random.bin newdata.bin
At this point cmp returns that the first char is different. Looking at a verbose output of cmp and turns out all values in newdata.bin are 0.
CodePudding user response:
Bash strings cannot hold arbitrary binary data because the ASCII NUL character is used as a string terminator.
One way to do what you want to do is to put the data in files instead of variables and use cmp
to compare the files.
Another option is to store cryptographic hashes of the data in Bash variables. This Shellcheck-clean code demonstrates the idea:
#! /bin/bash -p
partition_path=testpart
position_in_partition=10
sha256_1=$( exec 3>&1
head -c 5MB /dev/urandom \
| tee >(sha256sum >&3) \
| dd of="$partition_path" bs=1 \
seek="$position_in_partition" count=5MB)
sha256_2=$(dd if="$partition_path" bs=1 \
skip="$position_in_partition" count=5MB \
| sha256sum)
[[ $sha256_1 == "$sha256_2" ]] && echo 'data write successful'
- You'll need to set the
partition_path
andposition_in_partion
variables to values that are appropriate for you. exec 3>&1
connects file descriptor 3 to the stream that is used to read the value ofsha256_1
.tee >(sha256sum >&3)
uses the standardtee
utility and Bash process substitution to copy the pipeline data as input to asha256sum
process whose output is redirected to file descriptor 3. The effect of this is that thesha256sum
output (with the trailing newline removed) becomes the value of thesha256_1
variable.- You can use a stronger cryptographic hash function by replacing
sha256sum
with (for example)sha512sum
.
CodePudding user response:
Here's a simpler approach which just saves the data in a temporary file.
#!/bin/sh
set -e
random_data=$(mktemp -t ideone.XXXXXXXX) || exit
trap 'rm -rf "$t"' EXIT
dd if=/dev/urandom bs=10240 count=512 of="$random_data"
dd if="$random_data" of=<partition_path> bs=1 seek=<position_in_partition> count=<5MB>
if dd if=<partition_path> bs=1 skip=<position_in_partition> count=<5MB> |
cmp "$random_data"
then
echo "data write successful"
fi