Coverage Report

Created: 2025-12-14 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/topology/lvm.c
Line
Count
Source
1
/*
2
 * lvm topology
3
 * -- this is fallback for old systems where the topology information is not
4
 *    exported by sysfs
5
 *
6
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
7
 *
8
 * This file may be redistributed under the terms of the
9
 * GNU Lesser General Public License.
10
 *
11
 */
12
#include <errno.h>
13
#include <fcntl.h>
14
#include <stdint.h>
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <sys/stat.h>
19
#include <sys/types.h>
20
#include <unistd.h>
21
22
#include "topology.h"
23
24
#ifndef LVM_BLK_MAJOR
25
0
# define LVM_BLK_MAJOR     58
26
#endif
27
28
static int is_lvm_device(dev_t devno)
29
0
{
30
0
  if (major(devno) == LVM_BLK_MAJOR)
31
0
    return 1;
32
0
  return blkid_driver_has_major("lvm", major(devno));
33
0
}
34
35
static int probe_lvm_tp(blkid_probe pr,
36
    const struct blkid_idmag *mag __attribute__((__unused__)))
37
0
{
38
0
  const char * const paths[] = {
39
0
    "/usr/local/sbin/lvdisplay",
40
0
    "/usr/sbin/lvdisplay",
41
0
    "/sbin/lvdisplay"
42
0
  };
43
0
  int lvpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
44
0
  FILE *stream = NULL;
45
0
  char *cmd = NULL, *devname = NULL, buf[1024];
46
0
  size_t i;
47
0
  dev_t devno = blkid_probe_get_devno(pr);
48
49
0
  if (!devno)
50
0
    goto nothing;   /* probably not a block device */
51
0
  if (!is_lvm_device(devno))
52
0
    goto nothing;
53
54
0
  for (i = 0; i < ARRAY_SIZE(paths); i++) {
55
0
    struct stat sb;
56
0
    if (stat(paths[i], &sb) == 0) {
57
0
      cmd = (char *) paths[i];
58
0
      break;
59
0
    }
60
0
  }
61
62
0
  if (!cmd)
63
0
    goto nothing;
64
65
0
  devname = blkid_devno_to_devname(devno);
66
0
  if (!devname)
67
0
    goto nothing;
68
69
0
  if (pipe(lvpipe) < 0) {
70
0
    DBG(LOWPROBE, ul_debug("Failed to open pipe: errno=%d", errno));
71
0
    goto nothing;
72
0
  }
73
74
0
  switch (fork()) {
75
0
  case 0:
76
0
  {
77
0
    char *lvargv[3];
78
79
    /* Plumbing */
80
0
    close(lvpipe[0]);
81
82
0
    if (lvpipe[1] != STDOUT_FILENO)
83
0
      dup2(lvpipe[1], STDOUT_FILENO);
84
85
0
    if (drop_permissions() != 0)
86
0
       _exit(1);
87
88
0
    lvargv[0] = cmd;
89
0
    lvargv[1] = devname;
90
0
    lvargv[2] = NULL;
91
92
0
    execv(lvargv[0], lvargv);
93
94
0
    DBG(LOWPROBE, ul_debug("Failed to execute %s: errno=%d", cmd, errno));
95
0
    _exit(1);
96
0
  }
97
0
  case -1:
98
0
    DBG(LOWPROBE, ul_debug("Failed to forking: errno=%d", errno));
99
0
    goto nothing;
100
0
  default:
101
0
    break;
102
0
  }
103
104
0
  stream = fdopen(lvpipe[0], "r" UL_CLOEXECSTR);
105
0
  if (!stream)
106
0
    goto nothing;
107
108
0
  while (fgets(buf, sizeof(buf), stream) != NULL) {
109
0
    if (!strncmp(buf, "Stripes", 7))
110
0
      ignore_result( sscanf(buf, "Stripes %d", &stripes) );
111
112
0
    if (!strncmp(buf, "Stripe size", 11))
113
0
      ignore_result( sscanf(buf, "Stripe size (KByte) %d", &stripesize) );
114
0
  }
115
116
0
  if (!stripes)
117
0
    goto nothing;
118
119
0
  blkid_topology_set_minimum_io_size(pr, stripesize << 10);
120
0
  blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
121
122
0
  free(devname);
123
0
  fclose(stream);
124
0
  close(lvpipe[1]);
125
0
  return 0;
126
127
0
nothing:
128
0
  free(devname);
129
0
  if (stream)
130
0
    fclose(stream);
131
0
  else if (lvpipe[0] != -1)
132
0
    close(lvpipe[0]);
133
0
  if (lvpipe[1] != -1)
134
0
    close(lvpipe[1]);
135
0
  return 1;
136
0
}
137
138
const struct blkid_idinfo lvm_tp_idinfo =
139
{
140
  .name   = "lvm",
141
  .probefunc  = probe_lvm_tp,
142
  .magics   = BLKID_NONE_MAGIC
143
};
144