fix(payload-import): align with pre-util-linux toolchain by removing mount/S_ISBLK dependencies and probing only existing block nodes

This commit is contained in:
vxtls 2026-03-02 09:01:30 -05:00
parent c37acaaebe
commit 25f8311767
2 changed files with 32 additions and 183 deletions

View file

@ -7,8 +7,34 @@ set -ex
if [ "${PAYLOAD_REQUIRED}" = True ]; then
mkdir -p /external/distfiles
if ! payload-import /external/distfiles; then
echo "payload-import failed: no payload image found on block devices." >&2
found_payload=0
if [ -r /proc/partitions ]; then
while read -r major minor blocks name; do
case "${name}" in
""|name|ram*|loop*|fd*|sr*|md*|dm-*|nbd*)
continue
;;
*[0-9])
continue
;;
esac
dev_path="/dev/${name}"
[ -b "${dev_path}" ] || mknod -m 600 "${dev_path}" b "${major}" "${minor}" >/dev/null 2>&1 || :
done < /proc/partitions
fi
for dev_path in /dev/*; do
[ -b "${dev_path}" ] || continue
if payload-import --probe "${dev_path}"; then
payload-import --device "${dev_path}" /external/distfiles
found_payload=1
break
fi
done
if [ "${found_payload}" != 1 ]; then
echo "payload-import failed: no payload image found on block devices under /dev." >&2
exit 1
fi
fi

View file

@ -2,12 +2,10 @@
/* SPDX-License-Identifier: MIT */
#include <errno.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAGIC "LBPAYLD1"
@ -15,11 +13,6 @@
#define MAX_NAME_LEN 1024
#define COPY_BUFSZ 65536
/* mount(2) is available in the bootstrap libc, but some header stacks
* don't expose a prototype consistently. */
extern int mount(const char *source, const char *target,
const char *filesystemtype, unsigned int mountflags, const void *data);
static unsigned int read_u32le(const unsigned char *buf)
{
return (unsigned int)buf[0]
@ -113,55 +106,6 @@ static int has_payload_magic(const char *path)
return 0;
}
static int starts_with(const char *s, const char *prefix)
{
while (*prefix != 0) {
if (*s != *prefix) {
return 0;
}
s++;
prefix++;
}
return 1;
}
static int ends_with_digit(const char *s)
{
char c = 0;
while (*s != 0) {
c = *s;
s++;
}
return c >= '0' && c <= '9';
}
static int is_proc_partition_candidate(const char *name)
{
if (*name == 0 || strcmp(name, "name") == 0) {
return 0;
}
if (starts_with(name, "ram")
|| starts_with(name, "loop")
|| starts_with(name, "fd")
|| starts_with(name, "sr")
|| starts_with(name, "md")
|| starts_with(name, "dm-")
|| starts_with(name, "nbd")) {
return 0;
}
if (ends_with_digit(name)) {
/* Skip partitions; payload is attached as a whole disk. */
return 0;
}
return 1;
}
static unsigned int mkdev_u8(unsigned int major, unsigned int minor)
{
return ((major & 0xFFU) << 8) | (minor & 0xFFU);
}
static int extract_payload(const char *device, const char *dest_dir)
{
FILE *in;
@ -281,121 +225,13 @@ static int extract_payload(const char *device, const char *dest_dir)
return 0;
}
static int ensure_proc_partitions(void)
{
struct stat st;
if (stat("/proc/partitions", &st) == 0) {
return 0;
}
if (stat("/proc", &st) != 0) {
if (mkdir("/proc", 0755) != 0 && errno != EEXIST) {
return 1;
}
}
if (mount("proc", "/proc", "proc", 0, (const void *)0) != 0) {
return 1;
}
if (stat("/proc/partitions", &st) != 0) {
return 1;
}
return 0;
}
static int import_from_proc_partitions(const char *dest_dir)
{
FILE *fp;
char line[256];
if (ensure_proc_partitions() != 0) {
return 1;
}
fp = fopen("/proc/partitions", "r");
if (fp == NULL) {
return 1;
}
while (fgets(line, sizeof(line), fp) != NULL) {
unsigned int major, minor, blocks;
char name[64];
char dev_path[96];
if (sscanf(line, " %u %u %u %63s", &major, &minor, &blocks, name) != 4) {
continue;
}
if (!is_proc_partition_candidate(name)) {
continue;
}
if (snprintf(dev_path, sizeof(dev_path), "/dev/%s", name) >= (int)sizeof(dev_path)) {
continue;
}
if (access(dev_path, F_OK) != 0) {
if (mknod(dev_path, S_IFBLK | 0600, mkdev_u8(major, minor)) != 0) {
continue;
}
}
if (has_payload_magic(dev_path) == 0) {
fclose(fp);
return extract_payload(dev_path, dest_dir);
}
}
fclose(fp);
return 2;
}
static int import_from_dev_nodes(const char *dest_dir)
{
DIR *dir;
struct dirent *entry;
dir = opendir("/dev");
if (dir == NULL) {
return 2;
}
entry = readdir(dir);
while (entry != NULL) {
char path[512];
struct stat st;
if (entry->d_name[0] == '.') {
entry = readdir(dir);
continue;
}
if (snprintf(path, sizeof(path), "/dev/%s", entry->d_name) >= (int)sizeof(path)) {
entry = readdir(dir);
continue;
}
if (lstat(path, &st) != 0 || !S_ISBLK(st.st_mode)) {
entry = readdir(dir);
continue;
}
if (has_payload_magic(path) == 0) {
closedir(dir);
return extract_payload(path, dest_dir);
}
entry = readdir(dir);
}
closedir(dir);
return 2;
}
static void usage(const char *name)
{
fprintf(stderr,
"Usage:\n"
" %s --probe <device>\n"
" %s --from-proc <dest-dir>\n"
" %s [--device <device>] <dest-dir>\n",
name, name, name);
" %s --device <device> <dest-dir>\n",
name, name);
}
int main(int argc, char **argv)
@ -407,9 +243,6 @@ int main(int argc, char **argv)
if (argc == 3 && strcmp(argv[1], "--probe") == 0) {
return has_payload_magic(argv[2]);
}
if (argc == 3 && strcmp(argv[1], "--from-proc") == 0) {
return import_from_proc_partitions(argv[2]);
}
for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--device") == 0) {
@ -427,20 +260,10 @@ int main(int argc, char **argv)
}
}
if (dest_dir == NULL) {
if (device == NULL || dest_dir == NULL) {
usage(argv[0]);
return 1;
}
if (device != NULL) {
return extract_payload(device, dest_dir);
}
i = import_from_proc_partitions(dest_dir);
if (i == 0) {
return 0;
}
if (i == 1) {
fputs("payload-import: /proc/partitions unavailable, falling back to /dev scan\n", stderr);
}
return import_from_dev_nodes(dest_dir);
return extract_payload(device, dest_dir);
}