| /* |
| * device-mapper (dm) topology |
| * -- this is fallback for old systems where the topology information is not |
| * exported by sysfs |
| * |
| * Copyright (C) 2009 Karel Zak <kzak@redhat.com> |
| * |
| * This file may be redistributed under the terms of the |
| * GNU Lesser General Public License. |
| * |
| */ |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <sys/sysmacros.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #include "topology.h" |
| |
| static int is_dm_device(dev_t devno) |
| { |
| return blkid_driver_has_major("device-mapper", major(devno)); |
| } |
| |
| static int probe_dm_tp(blkid_probe pr, |
| const struct blkid_idmag *mag __attribute__((__unused__))) |
| { |
| const char *paths[] = { |
| "/usr/local/sbin/dmsetup", |
| "/usr/sbin/dmsetup", |
| "/sbin/dmsetup" |
| }; |
| int dmpipe[] = { -1, -1 }, stripes, stripesize; |
| char *cmd = NULL; |
| FILE *stream = NULL; |
| long long offset, size; |
| size_t i; |
| dev_t devno = blkid_probe_get_devno(pr); |
| |
| if (!devno) |
| goto nothing; /* probably not a block device */ |
| if (!is_dm_device(devno)) |
| goto nothing; |
| |
| for (i = 0; i < ARRAY_SIZE(paths); i++) { |
| struct stat sb; |
| if (stat(paths[i], &sb) == 0) { |
| cmd = (char *) paths[i]; |
| break; |
| } |
| } |
| |
| if (!cmd) |
| goto nothing; |
| if (pipe(dmpipe) < 0) { |
| DBG(LOWPROBE, ul_debug("Failed to open pipe: errno=%d", errno)); |
| goto nothing; |
| } |
| |
| switch (fork()) { |
| case 0: |
| { |
| char *dmargv[7], maj[16], min[16]; |
| |
| /* Plumbing */ |
| close(dmpipe[0]); |
| |
| if (dmpipe[1] != STDOUT_FILENO) |
| dup2(dmpipe[1], STDOUT_FILENO); |
| |
| /* The libblkid library could linked with setuid programs */ |
| if (setgid(getgid()) < 0) |
| exit(1); |
| if (setuid(getuid()) < 0) |
| exit(1); |
| |
| snprintf(maj, sizeof(maj), "%d", major(devno)); |
| snprintf(min, sizeof(min), "%d", minor(devno)); |
| |
| dmargv[0] = cmd; |
| dmargv[1] = "table"; |
| dmargv[2] = "-j"; |
| dmargv[3] = maj; |
| dmargv[4] = "-m"; |
| dmargv[5] = min; |
| dmargv[6] = NULL; |
| |
| execv(dmargv[0], dmargv); |
| |
| DBG(LOWPROBE, ul_debug("Failed to execute %s: errno=%d", cmd, errno)); |
| exit(1); |
| } |
| case -1: |
| DBG(LOWPROBE, ul_debug("Failed to forking: errno=%d", errno)); |
| goto nothing; |
| default: |
| break; |
| } |
| |
| stream = fdopen(dmpipe[0], "r" UL_CLOEXECSTR); |
| if (!stream) |
| goto nothing; |
| |
| if (fscanf(stream, "%lld %lld striped %d %d ", |
| &offset, &size, &stripes, &stripesize) != 0) |
| goto nothing; |
| |
| blkid_topology_set_minimum_io_size(pr, stripesize << 9); |
| blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 9); |
| |
| fclose(stream); |
| close(dmpipe[1]); |
| return 0; |
| |
| nothing: |
| if (stream) |
| fclose(stream); |
| else if (dmpipe[0] != -1) |
| close(dmpipe[0]); |
| if (dmpipe[1] != -1) |
| close(dmpipe[1]); |
| return 1; |
| } |
| |
| const struct blkid_idinfo dm_tp_idinfo = |
| { |
| .name = "dm", |
| .probefunc = probe_dm_tp, |
| .magics = BLKID_NONE_MAGIC |
| }; |
| |