mkimg: Fix parsing of filenames containing colons

When using PART_KIND_FILE (-p type:=filename), mkimg uses a colon
to separate an optional offset (e.g., filename:offset).

strsep() was being used to split the string at the first colon.
This caused failures when the filename itself contained a colon
(e.g., "th:is").

This patch uses stat() to check if the entire string exists as a
file. If so, use it directly without splitting.

If the full string is not a valid file, fall back to splitting
at the right-most colon using strrchr().

Uses errc() to fail and exit immediately when an existing directory
is input instead of a file in PART_KIND_FILE mode.

PR: 257960
Signed-off-by: Aaditya Singh <[email protected]>
Reviewed by: jlduran
Pull Request: https://github.com/freebsd/freebsd-src/pull/2041
This commit is contained in:
Aaditya Singh authored and Warner Losh committed 2026-04-16 00:05:21 -06:00
1 parent ee12645ec7
commit 50c1240ebf
1 file changed
+21 -3
+21 -3
View File
@@ -446,6 +446,8 @@ mkimg(void)
{
FILE *fp;
struct part *part;
struct stat sb;
char *p;
lba_t block, blkoffset;
uint64_t bytesize, byteoffset;
char *size, *offset;
@@ -468,12 +470,28 @@ mkimg(void)
/* Look for an offset. Set size too if we can. */
switch (part->kind) {
case PART_KIND_SIZE:
case PART_KIND_FILE:
offset = part->contents;
size = strsep(&offset, ":");
if (part->kind == PART_KIND_SIZE &&
expand_number(size, &bytesize) == -1)
if (expand_number(size, &bytesize) == -1)
error = errno;
break;
case PART_KIND_FILE:
size = part->contents;
if (stat(part->contents, &sb) == 0) {
if (S_ISDIR(sb.st_mode)) {
errc(EX_IOERR, EISDIR, "partition %d",
part->index + 1);
}
offset = NULL;
} else {
p = strrchr(part->contents, ':');
if (p != NULL) {
*p = '\0';
offset = p + 1;
} else {
offset = NULL;
}
}
if (offset != NULL) {
if (*offset != '+')
abs_offset = true;