helper-scripts/ddusb.py

96 lines
2.5 KiB
Python
Raw Normal View History

#!/usr/bin/python3
"""Wrapper script for using dd to write to a USB drive."""
2018-10-13 13:07:39 -07:00
import argparse
2019-03-07 22:51:56 -08:00
import glob
2018-10-13 13:07:39 -07:00
import pathlib
2019-03-07 22:51:56 -08:00
import re
2018-10-13 13:07:39 -07:00
import subprocess
2019-03-07 22:51:56 -08:00
# ========== Constants ==========
COMMENT_PATTERN = "^[#;]"
2019-03-07 22:51:56 -08:00
EXCLUDE_FILE = "/etc/helper-scripts/ddusb-exclude.conf"
# ========== Functions ==========
def read_exclude_file(exclude_file):
"""Read and return a list of exclusion paths/globs,
removing any lines that begin with COMMENT_PATTERN.
:param exclude_file: path to the exclusion file
:type exclude_file: str, bytes, or path-like object
:returns: a list containing non-commented lines from the
exclusion file
:rtype: list
"""
with open(exclude_file, "r") as excludes:
lines = [
l.strip("\n")
for l in excludes.readlines()
if not re.match(COMMENT_PATTERN, l)
]
return lines
def expand_globs(*globs):
"""For each glob given, expand these globs and return a list
containing each glob expanded.
:param globs: patterns to expand
:type globs: str
:returns: all expanded globs aggregated together
:rtype: list
"""
expanded_globs = []
for line in globs:
expanded_globs.extend(glob.glob(line, recursive=True))
return expanded_globs
# ========== Main Script ==========
parser = argparse.ArgumentParser()
parser.add_argument("-b", "--bs", default=512, help="block size", metavar="bs")
parser.add_argument("input_file", help="input file to write")
parser.add_argument("output_file", help="output block device")
args = parser.parse_args()
2018-10-23 15:33:04 -07:00
block_size = args.bs
input_file = args.input_file
block_device = args.output_file
2018-10-13 13:07:39 -07:00
# Ensure that block_device is really a block device
if not pathlib.Path(block_device).is_block_device():
2019-03-07 22:51:56 -08:00
print(f'Error: "{block_device}" is not a block device')
exit(1)
2018-10-13 13:07:39 -07:00
2019-03-07 22:51:56 -08:00
# Check if block_device is excluded
exclude_patterns = read_exclude_file(EXCLUDE_FILE)
device_blacklist = expand_globs(*exclude_patterns)
if block_device in device_blacklist:
print(f'Error: "{block_device}" is blacklisted from running dd')
exit(2)
print(f"Input file: {input_file}")
print(f"Block device: {block_device}")
print(f"Block size: {block_size}")
try:
subprocess.run(
[
"dd",
f"if={input_file}",
f"of={block_device}",
f"bs={block_size}",
"status=progress",
],
check=True,
)
except subprocess.CalledProcessError:
2019-03-07 22:51:56 -08:00
exit(3)
else:
2019-03-07 22:51:56 -08:00
subprocess.run("sync")