+static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
+ struct statfs sfs;
+ struct stat st, st2;
+ char *t;
+ blkid_probe b = NULL;
+ int r;
+ const char *v;
+
+ if (statfs(p, &sfs) < 0) {
+ fprintf(stderr, "Failed to check file system type of %s: %m\n", p);
+ return -errno;
+ }
+
+ if (sfs.f_type != 0x4d44) {
+ fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p);
+ return -ENODEV;
+ }
+
+ if (stat(p, &st) < 0) {
+ fprintf(stderr, "Failed to determine block device node of %s: %m\n", p);
+ return -errno;
+ }
+
+ if (major(st.st_dev) == 0) {
+ fprintf(stderr, "Block device node of %p is invalid.\n", p);
+ return -ENODEV;
+ }
+
+ r = asprintf(&t, "%s/..", p);
+ if (r < 0) {
+ fprintf(stderr, "Out of memory.\n");
+ return -ENOMEM;
+ }
+
+ r = stat(t, &st2);
+ free(t);
+ if (r < 0) {
+ fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p);
+ return -errno;
+ }
+
+ if (st.st_dev == st2.st_dev) {
+ fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p);
+ return -ENODEV;
+ }
+
+ r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
+ if (r < 0) {
+ fprintf(stderr, "Out of memory.\n");
+ return -ENOMEM;
+ }
+
+ errno = 0;
+ b = blkid_new_probe_from_filename(t);
+ free(t);
+ if (!b) {
+ if (errno != 0) {
+ fprintf(stderr, "Failed to open file system %s: %m\n", p);
+ return -errno;
+ }
+
+ fprintf(stderr, "Out of memory.\n");
+ return -ENOMEM;
+ }
+
+ blkid_probe_enable_superblocks(b, 1);
+ blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
+ blkid_probe_enable_partitions(b, 1);
+ blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
+
+ errno = 0;
+ r = blkid_do_safeprobe(b);
+ if (r == -2) {
+ fprintf(stderr, "File system %s is ambigious.\n", p);
+ r = -ENODEV;
+ goto fail;
+ } else if (r == 1) {
+ fprintf(stderr, "File system %s does not contain a label.\n", p);
+ r = -ENODEV;
+ goto fail;
+ } else if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+
+ if (strcmp(v, "vfat") != 0) {
+ fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p);
+ r = -ENODEV;
+ goto fail;
+ }
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+
+ if (strcmp(v, "gpt") != 0) {
+ fprintf(stderr, "File system %s is not on a GPT partition table.\n", p);
+ r = -ENODEV;
+ goto fail;
+ }
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+
+ if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) {
+ r = -ENODEV;
+ fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p);
+ goto fail;
+ }
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+ sd_id128_from_string(v, uuid);
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+ *part = strtoul(v, NULL, 10);
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
+ if (r != 0) {
+ r = errno ? -errno : -EIO;
+ fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
+ goto fail;
+ }
+ *pstart = strtoul(v, NULL, 10);