+
+int tools_wipe_all_signatures(const char *path, bool exclusive, bool only_luks)
+{
+ int fd, flags, r;
+ blk_probe_status pr;
+ struct stat st;
+ struct blkid_handle *h = NULL;
+
+ if (!blk_supported()) {
+ log_dbg("Blkid support disabled.");
+ return 0;
+ }
+
+ if (stat(path, &st)) {
+ log_err(_("Failed to stat device %s."), path);
+ return -EINVAL;
+ }
+
+ flags = O_RDWR;
+ if (S_ISBLK(st.st_mode) && exclusive)
+ flags |= O_EXCL;
+
+ /* better than opening regular file with O_EXCL (undefined) */
+ /* coverity[toctou] */
+ fd = open(path, flags); /* lgtm[cpp/toctou-race-condition] */
+ if (fd < 0) {
+ if (errno == EBUSY)
+ log_err(_("Cannot exclusively open %s, device in use."), path);
+ else
+ log_err(_("Failed to open file %s in read/write mode."), path);
+ return -EINVAL;
+ }
+
+ if ((r = blk_init_by_fd(&h, fd))) {
+ log_err(_("Failed to initialize device signature probes."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ blk_set_chains_for_wipes(h);
+ if (only_luks && (r = blk_superblocks_only_luks(h))) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ while ((pr = blk_probe(h)) < PRB_EMPTY) {
+ if (blk_is_partition(h))
+ log_verbose(_("Existing '%s' partition signature on device %s will be wiped."),
+ blk_get_partition_type(h), path);
+ if (blk_is_superblock(h))
+ log_verbose(_("Existing '%s' superblock signature on device %s will be wiped."),
+ blk_get_superblock_type(h), path);
+ if (blk_do_wipe(h) || fsync(fd)) {
+ log_err(_("Failed to wipe device signature."));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (pr != PRB_EMPTY) {
+ log_err(_("Failed to probe device %s for a signature."), path);
+ r = -EINVAL;
+ }
+out:
+ close(fd);
+ blk_free(h);
+ return r;
+}
+
+int tools_superblock_block_size(const char *device, char *sb_name, size_t sb_name_len, unsigned *r_block_size)
+{
+ struct blkid_handle *h;
+ const char *name;
+ int r = 0;
+
+ if (!r_block_size || !sb_name || sb_name_len < 1)
+ return -EINVAL;
+
+ if (!blk_supported()) {
+ log_dbg("Blkid support disabled.");
+ return 0;
+ }
+
+ if ((r = blk_init_by_path(&h, device))) {
+ log_err(_("Failed to initialize device signature probes."));
+ return -EINVAL;
+ }
+
+ blk_set_chains_for_superblocks(h);
+
+ switch (blk_probe(h)) {
+ case PRB_OK:
+ *r_block_size = blk_get_block_size(h);
+ if (!*r_block_size) /* same as not-found */
+ break;
+
+ if (!(name = blk_get_superblock_type(h))) {
+ r = -EINVAL;
+ break;
+ }
+
+ /* we don't mind truncating */
+ strncpy(sb_name, name, sb_name_len - 1);
+ sb_name[sb_name_len-1] = '\0';
+
+ log_dbg("Detected superblock %s on device %s (block size: %u).", sb_name, device, *r_block_size);
+ r = 1;
+ /* fall-through */
+ case PRB_EMPTY:
+ break;
+ default:
+ r = -EINVAL;
+ }
+
+ blk_free(h);
+
+ return r;
+}
+
+bool tools_blkid_supported(void)
+{
+ return blk_supported() != 0;
+}