Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/devname2devid.c
48529 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2007 Sun Microsystems, Inc. All rights reserved.24* Use is subject to license terms.25*26* Copyright (c) 2016, Intel Corporation.27*/2829#include <sys/types.h>30#include <sys/param.h>31#include <sys/stat.h>32#include <libudev.h>33#include <errno.h>34#include <stdio.h>35#include <stdlib.h>36#include <string.h>37#include <fcntl.h>3839/*40* Linux persistent device strings for vdev labels41*42* based on udev_device_get_devid() at zfs/lib/libzfs/libzfs_import.c43*/4445#define DEV_BYID_PATH "/dev/disk/by-id/"4647static int48udev_device_get_devid(struct udev_device *dev, char *bufptr, size_t buflen)49{50struct udev_list_entry *entry;51const char *bus;52char devbyid[MAXPATHLEN];5354/* The bus based by-id path is preferred */55bus = udev_device_get_property_value(dev, "ID_BUS");5657if (bus == NULL) {58const char *dm_uuid;5960/*61* For multipath nodes use the persistent uuid based identifier62*63* Example: 'dm-uuid-mpath-35000c5006304de3f'64*/65dm_uuid = udev_device_get_property_value(dev, "DM_UUID");66if (dm_uuid != NULL) {67(void) snprintf(bufptr, buflen, "dm-uuid-%s", dm_uuid);68return (0);69}70return (ENODATA);71}7273/*74* locate the bus specific by-id link75*76* Example: 'scsi-MG03SCA300_350000494a8cb3d67-part1'77*/78(void) snprintf(devbyid, sizeof (devbyid), "%s%s-", DEV_BYID_PATH, bus);79entry = udev_device_get_devlinks_list_entry(dev);80while (entry != NULL) {81const char *name;8283name = udev_list_entry_get_name(entry);84if (strncmp(name, devbyid, strlen(devbyid)) == 0) {85name += strlen(DEV_BYID_PATH);86(void) stpncpy(bufptr, name, buflen - 1);87bufptr[buflen - 1] = '\0';88return (0);89}90entry = udev_list_entry_get_next(entry);91}9293return (ENODATA);94}9596/*97* Usage: devname2devid <devicepath>98*99* Examples:100* # ./devname2devid /dev/sda1101* devid scsi-350000394a8caede4-part1102*103* # ./devname2devid /dev/dm-1104* devid: 'dm-uuid-mpath-35000c5006304de3f'105*106* This program accepts a disk or disk slice path and prints a107* device id.108*109* Exit values:110* 0 - means success111* 1 - means failure112*113*/114int115main(int argc, char *argv[])116{117struct udev *udev;118struct udev_device *dev = NULL;119char devid[128], nodepath[MAXPATHLEN];120char *device, *sysname;121int ret;122123if (argc == 1) {124(void) printf("%s <devicepath> [search path]\n", argv[0]);125exit(1);126}127device = argv[1];128129if ((udev = udev_new()) == NULL) {130perror("udev_new");131exit(1);132}133134/* resolve path to a runtime device node instance */135if (realpath(device, nodepath) == NULL) {136perror("realpath");137exit(1);138}139sysname = strrchr(nodepath, '/') + 1;140141if ((dev = udev_device_new_from_subsystem_sysname(udev, "block",142sysname)) == NULL) {143perror(sysname);144exit(1);145}146147if ((ret = udev_device_get_devid(dev, devid, sizeof (devid))) != 0) {148udev_device_unref(dev);149errno = ret;150perror(sysname);151exit(1);152}153154(void) printf("devid %s\n", devid);155156udev_device_unref(dev);157udev_unref(udev);158159return (0);160}161162163