Skip to content

Commit

Permalink
bmaptool: copy: add --removable-device option
Browse files Browse the repository at this point in the history
When enabled, 'bmaptool copy' writes to the destination file only if it
exists and is a removable block device.

Signed-off-by: Pascal Eberhard <[email protected]>
  • Loading branch information
pascaleberhard0se committed Mar 24, 2024
1 parent e799817 commit 1e1cbdb
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/man1/bmaptool.1
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,15 @@ used by \fBpsplash\fR. Each progress report consists of "PROGRESS" followed
by a space, an integer percentage and a newline.
.RE

.PP
\-\-removable\-device
.RS 2
Copy to destination only if it is a removable block device. This option is
recommended when writing on SD Card or USB key to avoid involuntary
destructive operations on non-removable disks. The copy command fails when the
destination file does not exist, is not a block device or is not removable.
.RE

.RE
.RE

Expand Down
43 changes: 43 additions & 0 deletions src/bmaptool/CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,45 @@ def open_files(args):
"(you specified the same path for them)"
)

if args.removable_device:
if not os.path.exists(args.dest):
# Missing device could occur often enough with removable devices,
# so trigger an error if it happens.
error_out(
f"Destination file {args.dest} does not exist. But the "
"removable-device option expects destination file to be an "
"existing device."
)
elif not stat.S_ISBLK(os.stat(args.dest).st_mode):
error_out(
f"Destination file {args.dest} is not a block device. But the "
"removable-device option expects the destination file to be "
"one."
)
else:
# Check whether the block device is removable by looking at
# /sys/block/<devicename>/removable attribute. The value in the
# file is "1" if removable, and "0" if not removable.
removable_path = os.path.join("/sys/block",
os.path.basename(args.dest),
"removable")
try:
removable_value = open(removable_path, "r").read(1)
except IOError as err:
error_out(
"Unable to detect removability of destination file "
f"{args.dest}. But the removable-device option requires "
"to be able to detect that it is a block device which is "
" removable. Cannot open sysfs attribute "
f"{removable_path} : {err}"
)
if removable_value != "1":
error_out(
f"Destination file {args.dest} is not a removable block "
"device. But the removable-device option expects it to be "
"one."
)

# If the destination file is under "/dev", but does not exist, print a
# warning. This is done in order to be more user-friendly, because
# sometimes users mean to write to a block device, them misspell its name.
Expand Down Expand Up @@ -696,6 +735,10 @@ def parse_arguments():
text = "write progress to a psplash pipe"
parser_copy.add_argument("--psplash-pipe", help=text)

# The --removable-device option
text = "copy on destination file only if it is a removable block device"
parser_copy.add_argument("--removable-device", action="store_true", help=text)

return parser.parse_args()


Expand Down

0 comments on commit 1e1cbdb

Please sign in to comment.