static int last_lba(blkid_probe pr, uint64_t *lba) { uint64_t sz = blkid_probe_get_size(pr); unsigned int ssz = blkid_probe_get_sectorsize(pr); if (sz < ssz) return -1; *lba = (sz / ssz) - 1ULL; return 0; }
int get_device_info(int fd, struct device_info *info) { blkid_probe probe; struct stat stat; int ret; *info = device_info_clueless; ret = fstat(fd, &stat); if (ret < 0) { perror("fstat on target failed"); return -1; } if (S_ISREG(stat.st_mode)) { /* there is nothing more to discover for an image file */ info->type = TYPE_FILE; info->partition = 0; info->size = stat.st_size; return 0; } if (!S_ISBLK(stat.st_mode)) { /* neither regular file nor block device? not usable */ info->type = TYPE_BAD; return 0; } probe = blkid_new_probe(); if (!probe) { return -1; } if (blkid_probe_set_device(probe, fd, 0, 0)) { blkid_free_probe(probe); return -1; } get_block_device_size(info, fd); get_block_geometry(info, fd); info->sector_size = blkid_probe_get_sectorsize(probe); /* use udev information if available, fall back to blkid probing */ if (udev_fill_info(info, &stat)) blkid_fill_info(info, probe); blkid_free_probe(probe); return 0; }
static int set_disk_properties(struct sync_disk *disk) { blkid_probe probe; blkid_topology topo; uint32_t sector_size, ss_logical, ss_physical; probe = blkid_new_probe_from_filename(disk->path); if (!probe) { log_error("cannot get blkid probe %s", disk->path); return -1; } topo = blkid_probe_get_topology(probe); if (!topo) { log_error("cannot get blkid topology %s", disk->path); blkid_free_probe(probe); return -1; } sector_size = blkid_probe_get_sectorsize(probe); ss_logical = blkid_topology_get_logical_sector_size(topo); ss_physical = blkid_topology_get_physical_sector_size(topo); blkid_free_probe(probe); if ((sector_size != ss_logical) || (sector_size != ss_physical) || (sector_size % 512)) { log_error("invalid disk sector size %u logical %u " "physical %u %s", sector_size, ss_logical, ss_physical, disk->path); return -1; } disk->sector_size = sector_size; return 0; }
/* * Reads GPT header to @hdr and returns a pointer to @hdr or NULL in case of * error. The function also returns GPT entries in @ents. * * Note, this function does not allocate any memory. The GPT header has fixed * size so we use stack, and @ents returns memory from libblkid buffer (so the * next blkid_probe_get_buffer() will overwrite this buffer). * * This function checks validity of header and entries array. A corrupted * header is not returned. */ static struct gpt_header *get_gpt_header( blkid_probe pr, struct gpt_header *hdr, struct gpt_entry **ents, uint64_t lba, uint64_t lastlba) { struct gpt_header *h; uint32_t crc; uint64_t lu, fu; size_t esz; uint32_t hsz, ssz; ssz = blkid_probe_get_sectorsize(pr); /* whole sector is allocated for GPT header */ h = (struct gpt_header *) get_lba_buffer(pr, lba, ssz); if (!h) return NULL; if (le64_to_cpu(h->signature) != GPT_HEADER_SIGNATURE) return NULL; hsz = le32_to_cpu(h->header_size); /* EFI: The HeaderSize must be greater than 92 and must be less * than or equal to the logical block size. */ if (hsz > ssz || hsz < sizeof(*h)) return NULL; /* Header has to be verified when header_crc32 is zero */ crc = count_crc32((unsigned char *) h, hsz, offsetof(struct gpt_header, header_crc32), sizeof(h->header_crc32)); if (crc != le32_to_cpu(h->header_crc32)) { DBG(LOWPROBE, ul_debug("GPT header corrupted")); return NULL; } /* Valid header has to be at MyLBA */ if (le64_to_cpu(h->my_lba) != lba) { DBG(LOWPROBE, ul_debug( "GPT->MyLBA mismatch with real position")); return NULL; } fu = le64_to_cpu(h->first_usable_lba); lu = le64_to_cpu(h->last_usable_lba); /* Check if First and Last usable LBA makes sense */ if (lu < fu || fu > lastlba || lu > lastlba) { DBG(LOWPROBE, ul_debug( "GPT->{First,Last}UsableLBA out of range")); return NULL; } /* The header has to be outside usable range */ if (fu < lba && lba < lu) { DBG(LOWPROBE, ul_debug("GPT header is inside usable area")); return NULL; } if (le32_to_cpu(h->num_partition_entries) == 0 || le32_to_cpu(h->sizeof_partition_entry) == 0 || ULONG_MAX / le32_to_cpu(h->num_partition_entries) < le32_to_cpu(h->sizeof_partition_entry)) { DBG(LOWPROBE, ul_debug("GPT entries undefined")); return NULL; } /* Size of blocks with GPT entries */ esz = le32_to_cpu(h->num_partition_entries) * le32_to_cpu(h->sizeof_partition_entry); /* The header seems valid, save it * (we don't care about zeros in hdr->reserved2 area) */ memcpy(hdr, h, sizeof(*h)); h = hdr; /* Read GPT entries */ *ents = (struct gpt_entry *) get_lba_buffer(pr, le64_to_cpu(h->partition_entries_lba), esz); if (!*ents) { DBG(LOWPROBE, ul_debug("GPT entries unreadable")); return NULL; } /* Validate entries */ crc = count_crc32((unsigned char *) *ents, esz, 0, 0); if (crc != le32_to_cpu(h->partition_entry_array_crc32)) { DBG(LOWPROBE, ul_debug("GPT entries corrupted")); return NULL; } return h; }
static inline unsigned char *get_lba_buffer(blkid_probe pr, uint64_t lba, size_t bytes) { return blkid_probe_get_buffer(pr, blkid_probe_get_sectorsize(pr) * lba, bytes); }
int main(int argc, char *argv[]) { int i, nparts; char *devname; blkid_probe pr; blkid_partlist ls; blkid_parttable root_tab; if (argc < 2) { fprintf(stderr, "usage: %s <device|file> " "-- prints partitions\n", program_invocation_short_name); return EXIT_FAILURE; } devname = argv[1]; pr = blkid_new_probe_from_filename(devname); if (!pr) err(EXIT_FAILURE, "%s: faild to create a new libblkid probe", devname); /* Binary interface */ ls = blkid_probe_get_partitions(pr); if (!ls) errx(EXIT_FAILURE, "%s: failed to read partitions\n", devname); /* * Print info about the primary (root) partition table */ root_tab = blkid_partlist_get_table(ls); if (!root_tab) errx(EXIT_FAILURE, "%s: does not contains any " "known partition table\n", devname); printf("size: %jd, sector size: %u, PT: %s, offset: %jd\n---\n", blkid_probe_get_size(pr), blkid_probe_get_sectorsize(pr), blkid_parttable_get_type(root_tab), blkid_parttable_get_offset(root_tab)); /* * List partitions */ nparts = blkid_partlist_numof_partitions(ls); if (!nparts) goto done; for (i = 0; i < nparts; i++) { const char *p; blkid_partition par = blkid_partlist_get_partition(ls, i); blkid_parttable tab = blkid_partition_get_table(par); printf("#%d: %10llu %10llu 0x%x", blkid_partition_get_partno(par), (unsigned long long) blkid_partition_get_start(par), (unsigned long long) blkid_partition_get_size(par), blkid_partition_get_type(par)); if (root_tab != tab) /* subpartition (BSD, Minix, ...) */ printf(" (%s)", blkid_parttable_get_type(tab)); p = blkid_partition_get_name(par); if (p) printf(" name='%s'", p); p = blkid_partition_get_uuid(par); if (p) printf(" uuid='%s'", p); p = blkid_partition_get_type_string(par); if (p) printf(" type='%s'", p); putc('\n', stdout); } done: blkid_free_probe(pr); return EXIT_SUCCESS; }