1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-07-08 11:39:02 +00:00

fix(iso_create): sanitize ISO9660 path components to replace invalid characters

Characters outside [A-Z0-9_] (e.g. hyphens in directory names like en-us)
were passed raw to pycdlib, causing it to reject them with an ISO9660
filename validation error. Replace invalid chars with underscores while
preserving original names in Rock Ridge / Joliet / UDF extension paths.

Fixes #5103

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alexei Znamensky 2026-05-10 22:39:29 +12:00
parent 87a42725e0
commit a43c0e61e4

View file

@ -222,6 +222,7 @@ boot_options:
"""
import os
import re
import traceback
PLATFORM_ID_MAP = {
@ -230,6 +231,24 @@ PLATFORM_ID_MAP = {
"mac": b"\x02",
}
_ISO9660_INVALID = re.compile(r"[^A-Z0-9_]")
def _sanitize_iso_path(path, is_file=False):
parts = path.split("/")
result = []
for i, part in enumerate(parts):
if not part:
result.append(part)
continue
if is_file and i == len(parts) - 1 and "." in part:
name, ext = part.upper().rsplit(".", 1)
result.append(_ISO9660_INVALID.sub("_", name) + "." + _ISO9660_INVALID.sub("_", ext))
else:
result.append(_ISO9660_INVALID.sub("_", part.upper()))
return "/".join(result)
PYCDLIB_IMP_ERR = None
try:
import pycdlib
@ -249,10 +268,11 @@ def add_file(module, iso_file=None, src_file=None, file_path=None, rock_ridge=No
# In standard ISO interchange level 1, file names have a maximum of 8 characters, followed by a required dot,
# followed by a maximum 3 character extension, followed by a semicolon and a version
file_name = os.path.basename(file_path)
sanitized_path = _sanitize_iso_path(file_path, is_file=True)
if "." not in file_name:
file_in_iso_path = f"{file_path.upper()}.;1"
file_in_iso_path = f"{sanitized_path}.;1"
else:
file_in_iso_path = f"{file_path.upper()};1"
file_in_iso_path = f"{sanitized_path};1"
if rock_ridge:
rr_name = file_name
if use_joliet:
@ -271,7 +291,7 @@ def add_directory(module, iso_file=None, dir_path=None, rock_ridge=None, use_jol
rr_name = None
joliet_path = None
udf_path = None
iso_dir_path = dir_path.upper()
iso_dir_path = _sanitize_iso_path(dir_path)
if rock_ridge:
rr_name = os.path.basename(dir_path)
if use_joliet:
@ -419,10 +439,11 @@ def main():
if boot_options:
boot_file = boot_options["boot_file"]
boot_file_basename = os.path.basename(boot_file)
sanitized_boot_path = _sanitize_iso_path(f"/{boot_file_basename}", is_file=True)
if "." not in boot_file_basename:
boot_iso_path = f"/{boot_file_basename.upper()}.;1"
boot_iso_path = f"{sanitized_boot_path}.;1"
else:
boot_iso_path = f"/{boot_file_basename.upper()};1"
boot_iso_path = f"{sanitized_boot_path};1"
add_file(
module,
iso_file=iso_file,