/* Given a partition (eg. /dev/sda2) then return the partition number * (eg. 2) and the total number of other partitions. */ static int get_partition_context (guestfs_h *g, const char *partition, int *partnum_ret, int *nr_partitions_ret) { int partnum, nr_partitions; CLEANUP_FREE char *device = NULL; CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *partitions = NULL; partnum = guestfs_part_to_partnum (g, partition); if (partnum == -1) return -1; device = guestfs_part_to_dev (g, partition); if (device == NULL) return -1; partitions = guestfs_part_list (g, device); if (partitions == NULL) return -1; nr_partitions = partitions->len; *partnum_ret = partnum; *nr_partitions_ret = nr_partitions; return 0; }
/* Windows Registry HKLM\SYSTEM\MountedDevices uses a blob of data * to store partitions. This blob is described here: * http://www.goodells.net/multiboot/partsigs.shtml * The following function maps this blob to a libguestfs partition * name, if possible. */ static char * map_registry_disk_blob (guestfs_h *g, const void *blob) { CLEANUP_FREE_STRING_LIST char **devices = NULL; CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *partitions = NULL; size_t i, j, len; uint64_t part_offset; /* First 4 bytes are the disk ID. Search all devices to find the * disk with this disk ID. */ devices = guestfs_list_devices (g); if (devices == NULL) return NULL; for (i = 0; devices[i] != NULL; ++i) { /* Read the disk ID. */ CLEANUP_FREE char *diskid = guestfs_pread_device (g, devices[i], 4, 0x01b8, &len); if (diskid == NULL) continue; if (len < 4) continue; if (memcmp (diskid, blob, 4) == 0) /* found it */ goto found_disk; } return NULL; found_disk: /* Next 8 bytes are the offset of the partition in bytes(!) given as * a 64 bit little endian number. Luckily it's easy to get the * partition byte offset from guestfs_part_list. */ memcpy (&part_offset, (char *) blob + 4, sizeof (part_offset)); part_offset = le64toh (part_offset); partitions = guestfs_part_list (g, devices[i]); if (partitions == NULL) return NULL; for (j = 0; j < partitions->len; ++j) { if (partitions->val[j].part_start == part_offset) /* found it */ goto found_partition; } return NULL; found_partition: /* Construct the full device name. */ return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num); }
void scan (size_t *worst_alignment, const char *prefix) { char **devices, *p; size_t i, j; size_t alignment; uint64_t start; struct guestfs_partition_list *parts; devices = guestfs_list_devices (g); if (devices == NULL) exit (EXIT_FAILURE); for (i = 0; devices[i] != NULL; ++i) { parts = guestfs_part_list (g, devices[i]); if (parts == NULL) exit (EXIT_FAILURE); /* Canonicalize the name of the device for printing. */ p = guestfs_canonical_device_name (g, devices[i]); if (p == NULL) exit (EXIT_FAILURE); free (devices[i]); devices[i] = p; for (j = 0; j < parts->len; ++j) { /* Start offset of the partition in bytes. */ start = parts->val[j].part_start; if (!quiet) { if (prefix) printf ("%s:", prefix); printf ("%s%d %12" PRIu64 " ", devices[i], (int) parts->val[j].part_num, start); } /* What's the alignment? */ if (start == 0) /* Probably not possible, but anyway. */ alignment = 64; else for (alignment = 0; (start & 1) == 0; alignment++, start /= 2) ; if (!quiet) { if (alignment < 10) printf ("%12" PRIu64 " ", UINT64_C(1) << alignment); else if (alignment < 64) printf ("%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10)); else printf ("- "); } if (alignment < *worst_alignment) *worst_alignment = alignment; if (alignment < 12) { /* Bad in general: < 4K alignment */ if (!quiet) printf ("bad (%s)\n", _("alignment < 4K")); } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */ if (!quiet) printf ("bad (%s)\n", _("alignment < 64K")); } else { if (!quiet) printf ("ok\n"); } } guestfs_free_partition_list (parts); free (devices[i]); } free (devices); }
static int scan (guestfs_h *g, const char *prefix, FILE *fp) { size_t i, j; size_t alignment; uint64_t start; int err; CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g); if (devices == NULL) return -1; for (i = 0; devices[i] != NULL; ++i) { CLEANUP_FREE char *name = NULL; CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *parts = guestfs_part_list (g, devices[i]); if (parts == NULL) return -1; /* Canonicalize the name of the device for printing. */ name = guestfs_canonical_device_name (g, devices[i]); if (name == NULL) return -1; for (j = 0; j < parts->len; ++j) { /* Start offset of the partition in bytes. */ start = parts->val[j].part_start; if (!quiet) { if (prefix) fprintf (fp, "%s:", prefix); fprintf (fp, "%s%d %12" PRIu64 " ", name, (int) parts->val[j].part_num, start); } /* What's the alignment? */ if (start == 0) /* Probably not possible, but anyway. */ alignment = 64; else for (alignment = 0; (start & 1) == 0; alignment++, start /= 2) ; if (!quiet) { if (alignment < 10) fprintf (fp, "%12" PRIu64 " ", UINT64_C(1) << alignment); else if (alignment < 64) fprintf (fp, "%12" PRIu64 "K ", UINT64_C(1) << (alignment - 10)); else fprintf (fp, "- "); } err = pthread_mutex_lock (&worst_alignment_mutex); assert (err == 0); if (alignment < worst_alignment) worst_alignment = alignment; err = pthread_mutex_unlock (&worst_alignment_mutex); assert (err == 0); if (alignment < 12) { /* Bad in general: < 4K alignment */ if (!quiet) fprintf (fp, "bad (%s)\n", _("alignment < 4K")); } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */ if (!quiet) fprintf (fp, "bad (%s)\n", _("alignment < 64K")); } else { if (!quiet) fprintf (fp, "ok\n"); } } } return 0; }