package/base-files: caldata: use dd iflag fullblock
authorJohn Thomson <git@johnthomson.fastmail.com.au>
Wed, 9 Dec 2020 03:03:04 +0000 (13:03 +1000)
committerPetr Štetiar <ynezz@true.cz>
Fri, 11 Dec 2020 12:48:24 +0000 (13:48 +0100)
This dd flag ensures that the requested size
is retrieved from pipes or special filesystems (if available).

Without this flag, on multi-core systems,
Piped or special filesystem data can be truncated
when a size greater than PIPE_BUF is requested.

Fixes: FS#3494
Fixes: 7557e7f ("package/base-files: caldata: work around dd's
limitation")
Cc: Thibaut VARÈNE <hacks@slashdirt.org>
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
package/base-files/Makefile
package/base-files/files/lib/functions/caldata.sh

index 0c612b73ca9bdfd6aceee3747805851ece65d4cf..fbcb6945920183656961db30b039f7c381d3cd2c 100644 (file)
@@ -12,7 +12,7 @@ include $(INCLUDE_DIR)/version.mk
 include $(INCLUDE_DIR)/feeds.mk
 
 PKG_NAME:=base-files
-PKG_RELEASE:=239
+PKG_RELEASE:=240
 PKG_FLAGS:=nonshared
 
 PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/
index e22c7d27e69f469bc87021b515d3a20ae749be67..2177cf8415326e2906460c0a7229e9fa3b484889 100644 (file)
@@ -3,6 +3,16 @@
 . /lib/functions.sh
 . /lib/functions/system.sh
 
+caldata_dd() {
+       local source=$1
+       local target=$2
+       local count=$(($3))
+       local offset=$(($4))
+
+       dd if=$source of=$target iflag=skip_bytes,fullblock bs=$count skip=$offset count=1 2>/dev/null
+       return $?
+}
+
 caldata_die() {
        echo "caldata: " "$*"
        exit 1
@@ -17,7 +27,7 @@ caldata_extract() {
        mtd=$(find_mtd_chardev $part)
        [ -n "$mtd" ] || caldata_die "no mtd device found for partition $part"
 
-       dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
+       caldata_dd $mtd /lib/firmware/$FIRMWARE $count $offset || \
                caldata_die "failed to extract calibration data from $mtd"
 }
 
@@ -34,7 +44,7 @@ caldata_extract_ubi() {
        ubi=$(nand_find_volume $ubidev $part)
        [ -n "$ubi" ] || caldata_die "no UBI volume found for $part"
 
-       dd if=/dev/$ubi of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
+       caldata_dd /dev/$ubi /lib/firmware/$FIRMWARE $count $offset || \
                caldata_die "failed to extract calibration data from $ubi"
 }
 
@@ -64,8 +74,7 @@ caldata_from_file() {
 
        [ -n "$target" ] || target=/lib/firmware/$FIRMWARE
 
-       # dd doesn't handle partial reads from special files: use cat
-       cat $source | dd of=$target iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
+       caldata_dd $source $target $count $offset || \
                caldata_die "failed to extract calibration data from $source"
 }
 
@@ -73,16 +82,20 @@ caldata_sysfsload_from_file() {
        local source=$1
        local offset=$(($2))
        local count=$(($3))
+       local target_dir="/sys/$DEVPATH"
+       local target="$target_dir/data"
 
-       # dd doesn't handle partial reads from special files: use cat
-       # test extract to /dev/null first
-       cat $source | dd of=/dev/null iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
-               caldata_die "failed to extract calibration data from $source"
+       [ -d "$target_dir" ] || \
+               caldata_die "no sysfs dir to write: $target"
 
-       # can't fail now
-       echo 1 > /sys/$DEVPATH/loading
-       cat $source | dd of=/sys/$DEVPATH/data iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null
-       echo 0 > /sys/$DEVPATH/loading
+       echo 1 > "$target_dir/loading"
+       caldata_dd $source $target $count $offset
+       if [ $? != 0 ]; then
+               echo 1 > "$target_dir/loading"
+               caldata_die "failed to extract calibration data from $source"
+       else
+               echo 0 > "$target_dir/loading"
+       fi
 }
 
 caldata_valid() {