gboolean disk_by_label(const gchar* label, gchar** device) { const char* devpath = NULL; blkid_dev dev = NULL; blkid_cache cache = NULL; *device = NULL; if (blkid_get_cache(&cache, "/dev/null") != 0) { LOG(MOD "Cannot get cache!\n"); return false; } if (blkid_probe_all(cache) != 0) { LOG(MOD "Probe all failed!\n"); return false; } dev = blkid_find_dev_with_tag(cache, "LABEL", label); if (!dev) { LOG(MOD "Device wiht label '%s' not found!\n", label); return false; } devpath = blkid_dev_devname(dev); if (!devpath) { LOG(MOD "Cannot get device name!\n"); return false; } *device = g_strdup(devpath); return true; }
static void print_tags(blkid_dev dev, char *show[], int output) { blkid_tag_iterate iter; const char *type, *value, *devname; int num = 1; if (!dev) return; if (output & OUTPUT_PRETTY_LIST) { pretty_print_dev(dev); return; } devname = blkid_dev_devname(dev); if (output & OUTPUT_DEVICE_ONLY) { printf("%s\n", devname); return; } iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value) == 0) { if (show[0] && !has_item(show, type)) continue; print_value(output, num++, devname, value, type, strlen(value)); } blkid_tag_iterate_end(iter); if (num > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) printf("\n"); }
static void print_tags(blkid_dev dev, char *show[], int numtag, int output) { blkid_tag_iterate iter; const char *type, *value; int i, first = 1; if (!dev) return; if (output & OUTPUT_PRETTY_LIST) { pretty_print_dev(dev); return; } if (output & OUTPUT_DEVICE_ONLY) { printf("%s\n", blkid_dev_devname(dev)); return; } iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value) == 0) { if (numtag && show) { for (i=0; i < numtag; i++) if (!strcmp(type, show[i])) break; if (i >= numtag) continue; } if (output & OUTPUT_VALUE_ONLY) { fputs(value, stdout); fputc('\n', stdout); } else { if (first) { printf("%s: ", blkid_dev_devname(dev)); first = 0; } fputs(type, stdout); fputs("=\"", stdout); safe_print(value, -1); fputs("\" ", stdout); } } blkid_tag_iterate_end(iter); if (!first && !(output & OUTPUT_VALUE_ONLY)) printf("\n"); }
/* Find the device id for a given blkid_dev. * FIXME: libblkid already has this info but lacks a function to expose it. */ static dev_t dev_to_devno(blkid_dev dev) { struct stat dev_stat; if (stat(blkid_dev_devname(dev), &dev_stat) < 0) return -1; if (!S_ISBLK(dev_stat.st_mode)) return -1; return dev_stat.st_rdev; }
static void pretty_print_dev(blkid_dev dev) { blkid_tag_iterate iter; const char *type, *value, *devname; const char *uuid = "", *fs_type = "", *label = ""; int len, mount_flags; char mtpt[80]; errcode_t retval; if (dev == NULL) { pretty_print_line("device", "fs_type", "label", "mount point", "UUID"); for (len=get_terminal_width()-1; len > 0; len--) fputc('-', stdout); fputc('\n', stdout); return; } devname = blkid_dev_devname(dev); if (access(devname, F_OK)) return; /* Get the uuid, label, type */ iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value) == 0) { if (!strcmp(type, "UUID")) uuid = value; if (!strcmp(type, "TYPE")) fs_type = value; if (!strcmp(type, "LABEL")) label = value; } blkid_tag_iterate_end(iter); /* Get the mount point */ mtpt[0] = 0; retval = ext2fs_check_mount_point(devname, &mount_flags, mtpt, sizeof(mtpt)); if (retval == 0) { if (mount_flags & EXT2_MF_MOUNTED) { if (!mtpt[0]) strcpy(mtpt, "(mounted, mtpt unknown)"); } else if (mount_flags & EXT2_MF_BUSY) strcpy(mtpt, "(in use)"); else strcpy(mtpt, "(not mounted)"); } pretty_print_line(devname, fs_type, label, mtpt, uuid); }
static void print_tags(blkid_dev dev, char *show[], int numtag, int output) { blkid_tag_iterate iter; const char *type, *value; int i, first = 1; if (!dev) return; if (output & OUTPUT_DEVICE_ONLY) { printf("%s\n", blkid_dev_devname(dev)); return; } iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value) == 0) { if (numtag && show) { for (i=0; i < numtag; i++) if (!strcmp(type, show[i])) break; if (i >= numtag) continue; } if (first && !(output & OUTPUT_VALUE_ONLY)) { printf("%s: ", blkid_dev_devname(dev)); first = 0; } if ((output & OUTPUT_VALUE_ONLY)) printf("%s\n", value); else printf("%s=\"%s\" ", type, value); } blkid_tag_iterate_end(iter); if (!first && !(output & OUTPUT_VALUE_ONLY)) printf("\n"); }
/* * Locate a device name from a token (NAME=value string), or (name, value) * pair. In the case of a token, value is ignored. If the "token" is not * of the form "NAME=value" and there is no value given, then it is assumed * to be the actual devname and a copy is returned. */ char *blkid_get_devname(blkid_cache cache, const char *token, const char *value) { blkid_dev dev; blkid_cache c = cache; char *t = 0, *v = 0; char *ret = NULL; if (!token) return NULL; if (!cache) { if (blkid_get_cache(&c, NULL) < 0) return NULL; } DBG(DEBUG_RESOLVE, printf("looking for %s%s%s %s\n", token, value ? "=" : "", value ? value : "", cache ? "in cache" : "from disk")); if (!value) { if (!strchr(token, '=')) { ret = blkid_strdup(token); goto out; } blkid_parse_tag_string(token, &t, &v); if (!t || !v) goto out; token = t; value = v; } dev = blkid_find_dev_with_tag(c, token, value); if (!dev) goto out; ret = blkid_strdup(blkid_dev_devname(dev)); out: if (t) free(t); if (v) free(v); if (!cache) { blkid_put_cache(c); } return (ret); }
static void print_tags(blkid_dev dev, char *show[], int output) { blkid_tag_iterate iter; const char *type, *value, *devname; int num = 1; static int first = 1; if (!dev) return; if (output & OUTPUT_PRETTY_LIST) { pretty_print_dev(dev); return; } devname = blkid_dev_devname(dev); if (output & OUTPUT_DEVICE_ONLY) { printf("%s\n", devname); return; } iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value) == 0) { if (show[0] && !has_item(show, type)) continue; if (num == 1 && !first && (output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST))) /* add extra line between output from more devices */ fputc('\n', stdout); print_value(output, num++, devname, value, type, strlen(value)); } blkid_tag_iterate_end(iter); if (num > 1) { if (!(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST))) printf("\n"); first = 0; } }
/* * Use libblkid to quickly search for zfs devices */ static int zpool_find_import_blkid(libzfs_handle_t *hdl, pool_list_t *pools) { blkid_cache cache; blkid_dev_iterate iter; blkid_dev dev; const char *devname; nvlist_t *config; int fd, err, num_labels; err = blkid_get_cache(&cache, NULL); if (err != 0) { (void) zfs_error_fmt(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "blkid_get_cache() %d"), err); goto err_blkid1; } err = blkid_probe_all(cache); if (err != 0) { (void) zfs_error_fmt(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "blkid_probe_all() %d"), err); goto err_blkid2; } iter = blkid_dev_iterate_begin(cache); if (iter == NULL) { (void) zfs_error_fmt(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "blkid_dev_iterate_begin()")); goto err_blkid2; } err = blkid_dev_set_search(iter, "TYPE", "zfs_member"); if (err != 0) { (void) zfs_error_fmt(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "blkid_dev_set_search() %d"), err); goto err_blkid3; } while (blkid_dev_next(iter, &dev) == 0) { devname = blkid_dev_devname(dev); if ((fd = open(devname, O_RDONLY)) < 0) continue; err = zpool_read_label(fd, &config, &num_labels); (void) close(fd); if (err != 0) { (void) no_memory(hdl); goto err_blkid3; } if (config != NULL) { err = add_config(hdl, pools, devname, 0, num_labels, config); if (err != 0) goto err_blkid3; } } err_blkid3: blkid_dev_iterate_end(iter); err_blkid2: blkid_put_cache(cache); err_blkid1: return (err); }
/* Resize the partition and notify the kernel. * returns: * CGPT_OK for resize successful or nothing to do * CGPT_FAILED on error */ static int resize_partition(CgptResizeParams *params, blkid_dev dev) { char *disk_devname; struct drive drive; GptHeader *header; GptEntry *entry; int gpt_retval, entry_index, entry_count; uint64_t free_bytes, last_free_lba, entry_size_lba; if ((disk_devname = dev_to_wholedevname(dev)) == NULL) { Error("Failed to find whole disk device for %s\n", blkid_dev_devname(dev)); return CGPT_FAILED; } if (DriveOpen(disk_devname, &drive, 0, O_RDWR) != CGPT_OK) { free(disk_devname); return CGPT_FAILED; } free(disk_devname); if (CGPT_OK != ReadPMBR(&drive)) { Error("Unable to read PMBR\n"); goto nope; } if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) { Error("GptSanityCheck() returned %d: %s\n", gpt_retval, GptError(gpt_retval)); goto nope; } // If either table is bad fix it! (likely if disk was extended) GptRepair(&drive.gpt); header = (GptHeader*)drive.gpt.primary_header; last_free_lba = header->last_usable_lba; entry_count = GetNumberOfEntries(&drive); entry_index = dev_to_partno(dev) - 1; if (entry_index < 0 || entry_index >= entry_count) { Error("Kernel and GPT disagree on the number of partitions!\n"); goto nope; } entry = GetEntry(&drive.gpt, PRIMARY, entry_index); // Scan entire table to determine if entry can grow. for (int i = 0; i < entry_count; i++) { GptEntry *other = GetEntry(&drive.gpt, PRIMARY, i); if (GuidIsZero(&other->type)) continue; if (other->starting_lba > entry->ending_lba && other->starting_lba - 1 < last_free_lba) { last_free_lba = other->starting_lba - 1; } } // Exit without doing anything if the size is too small free_bytes = (last_free_lba - entry->ending_lba) * drive.gpt.sector_bytes; if (entry->ending_lba >= last_free_lba || free_bytes < params->min_resize_bytes) { if (DriveClose(&drive, 0) != CGPT_OK) return CGPT_FAILED; else return CGPT_OK; } // Update and test partition table in memory entry->ending_lba = last_free_lba; entry_size_lba = entry->ending_lba - entry->starting_lba; UpdateAllEntries(&drive); gpt_retval = CheckEntries((GptEntry*)drive.gpt.primary_entries, (GptHeader*)drive.gpt.primary_header); if (gpt_retval != GPT_SUCCESS) { Error("CheckEntries() returned %d: %s\n", gpt_retval, GptError(gpt_retval)); goto nope; } // Notify kernel of new partition size via an ioctl. if (blkpg_resize_partition(drive.fd, dev_to_partno(dev), entry->starting_lba * drive.gpt.sector_bytes, entry_size_lba * drive.gpt.sector_bytes) < 0) { Error("Failed to notify kernel of new partition size: %s\n" "Leaving existing partition table in place.\n", strerror(errno)); goto nope; } UpdatePMBR(&drive, PRIMARY); if (WritePMBR(&drive) != CGPT_OK) { Error("Failed to write legacy MBR.\n"); goto nope; } // Whew! we made it! Flush to disk. return DriveClose(&drive, 1); nope: DriveClose(&drive, 0); return CGPT_FAILED; }