Coverage Report

Created: 2025-11-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/dev.c
Line
Count
Source
1
/*
2
 * dev.c - allocation/initialization/free routines for dev
3
 *
4
 * Copyright (C) 2001 Andreas Dilger
5
 * Copyright (C) 2003 Theodore Ts'o
6
 *
7
 * %Begin-Header%
8
 * This file may be redistributed under the terms of the
9
 * GNU Lesser General Public License.
10
 * %End-Header%
11
 */
12
13
#include <stdlib.h>
14
#include <string.h>
15
16
#include "blkidP.h"
17
18
/*
19
 * NOTE: reference manual is not structured as code. The following section is a generic
20
 * section for all high-level cache search+iterate routines.
21
 */
22
23
/**
24
 * SECTION:search
25
 * @title: Search and iterate
26
 * @short_description: search devices and iterate over devices in the cache.
27
 *
28
 * Note that high-level probing API provides information about superblocks
29
 * (filesystems/raids) only.  For partitions and topology is necessary to use
30
 * the low-level API.
31
 */
32
33
blkid_dev blkid_new_dev(void)
34
0
{
35
0
  blkid_dev dev;
36
37
0
  if (!(dev = calloc(1, sizeof(struct blkid_struct_dev))))
38
0
    return NULL;
39
40
0
  DBG(DEV, ul_debugobj(dev, "alloc"));
41
0
  INIT_LIST_HEAD(&dev->bid_devs);
42
0
  INIT_LIST_HEAD(&dev->bid_tags);
43
44
0
  return dev;
45
0
}
46
47
void blkid_free_dev(blkid_dev dev)
48
0
{
49
0
  if (!dev)
50
0
    return;
51
52
0
  DBG(DEV, ul_debugobj(dev, "freeing (%s)", dev->bid_name));
53
54
0
  list_del(&dev->bid_devs);
55
0
  while (!list_empty(&dev->bid_tags)) {
56
0
    blkid_tag tag = list_entry(dev->bid_tags.next,
57
0
             struct blkid_struct_tag,
58
0
             bit_tags);
59
0
    blkid_free_tag(tag);
60
0
  }
61
0
  free(dev->bid_xname);
62
0
  free(dev->bid_name);
63
0
  free(dev);
64
0
}
65
66
/*
67
 * Given a blkid device, return its name. The function returns the name
68
 * previously used for blkid_get_dev(). This name does not have to be canonical
69
 * (real path) name, but for example symlink.
70
 */
71
const char *blkid_dev_devname(blkid_dev dev)
72
0
{
73
0
  if (!dev)
74
0
    return NULL;
75
0
  if (dev->bid_xname)
76
0
    return dev->bid_xname;
77
0
  return dev->bid_name;
78
0
}
79
80
void blkid_debug_dump_dev(blkid_dev dev)
81
0
{
82
0
  struct list_head *p;
83
84
0
  if (!dev) {
85
0
    printf("  dev: NULL\n");
86
0
    return;
87
0
  }
88
89
0
  fprintf(stderr, "  dev: name = %s\n", dev->bid_name);
90
0
  fprintf(stderr, "  dev: DEVNO=\"0x%0lx\"\n", (unsigned long)dev->bid_devno);
91
0
  fprintf(stderr, "  dev: TIME=\"%lld.%lld\"\n", (long long)dev->bid_time, (long long)dev->bid_utime);
92
0
  fprintf(stderr, "  dev: PRI=\"%d\"\n", dev->bid_pri);
93
0
  fprintf(stderr, "  dev: flags = 0x%08X\n", dev->bid_flags);
94
95
0
  list_for_each(p, &dev->bid_tags) {
96
0
    blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
97
0
    if (tag)
98
0
      fprintf(stderr, "    tag: %s=\"%s\"\n", tag->bit_name,
99
0
             tag->bit_val);
100
0
    else
101
0
      fprintf(stderr, "    tag: NULL\n");
102
0
  }
103
0
}
104
105
/*
106
 * dev iteration routines for the public libblkid interface.
107
 *
108
 * These routines do not expose the list.h implementation, which are a
109
 * contamination of the namespace, and which force us to reveal far, far
110
 * too much of our internal implementation.  I'm not convinced I want
111
 * to keep list.h in the long term, anyway.  It's fine for kernel
112
 * programming, but performance is not the #1 priority for this
113
 * library, and I really don't like the trade-off of type-safety for
114
 * performance for this application.  [tytso:20030125.2007EST]
115
 */
116
117
/*
118
 * This series of functions iterate over all devices in a blkid cache
119
 */
120
0
#define DEV_ITERATE_MAGIC 0x01a5284c
121
122
struct blkid_struct_dev_iterate {
123
  int     magic;
124
  blkid_cache   cache;
125
  char      *search_type;
126
  char      *search_value;
127
  struct list_head  *p;
128
};
129
130
blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
131
0
{
132
0
  blkid_dev_iterate iter;
133
134
0
  if (!cache) {
135
0
    errno = EINVAL;
136
0
    return NULL;
137
0
  }
138
139
0
  iter = malloc(sizeof(struct blkid_struct_dev_iterate));
140
0
  if (iter) {
141
0
    iter->magic = DEV_ITERATE_MAGIC;
142
0
    iter->cache = cache;
143
0
    iter->p = cache->bic_devs.next;
144
0
    iter->search_type = NULL;
145
0
    iter->search_value = NULL;
146
0
  }
147
0
  return iter;
148
0
}
149
150
int blkid_dev_set_search(blkid_dev_iterate iter,
151
         const char *search_type, const char *search_value)
152
0
{
153
0
  char *new_type, *new_value;
154
155
0
  if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
156
0
      !search_value)
157
0
    return -1;
158
0
  new_type = strdup(search_type);
159
0
  new_value = strdup(search_value);
160
0
  if (!new_type || !new_value) {
161
0
    free(new_type);
162
0
    free(new_value);
163
0
    return -1;
164
0
  }
165
0
  free(iter->search_type);
166
0
  free(iter->search_value);
167
0
  iter->search_type = new_type;
168
0
  iter->search_value = new_value;
169
0
  return 0;
170
0
}
171
172
/*
173
 * Return 0 on success, -1 on error
174
 */
175
int blkid_dev_next(blkid_dev_iterate iter,
176
        blkid_dev *ret_dev)
177
0
{
178
0
  blkid_dev   dev;
179
180
0
  if  (!ret_dev || !iter || iter->magic != DEV_ITERATE_MAGIC)
181
0
    return -1;
182
0
  *ret_dev = NULL;
183
0
  while (iter->p != &iter->cache->bic_devs) {
184
0
    dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
185
0
    iter->p = iter->p->next;
186
0
    if (iter->search_type &&
187
0
        !blkid_dev_has_tag(dev, iter->search_type,
188
0
               iter->search_value))
189
0
      continue;
190
0
    *ret_dev = dev;
191
0
    return 0;
192
0
  }
193
0
  return -1;
194
0
}
195
196
void blkid_dev_iterate_end(blkid_dev_iterate iter)
197
0
{
198
0
  if (!iter || iter->magic != DEV_ITERATE_MAGIC)
199
0
    return;
200
0
  iter->magic = 0;
201
0
  free(iter->search_type);
202
0
  free(iter->search_value);
203
0
  free(iter);
204
0
}
205
206
#ifdef TEST_PROGRAM
207
#ifdef HAVE_GETOPT_H
208
#include <getopt.h>
209
#else
210
extern char *optarg;
211
extern int optind;
212
#endif
213
214
static void __attribute__((__noreturn__)) usage(char *prog)
215
{
216
  fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
217
  fprintf(stderr, "\tList all devices and exit\n");
218
  exit(1);
219
}
220
221
int main(int argc, char **argv)
222
{
223
  blkid_dev_iterate iter;
224
  blkid_cache     cache = NULL;
225
  blkid_dev   dev;
226
  int     c, ret;
227
  char      *tmp;
228
  char      *file = NULL;
229
  char      *search_type = NULL;
230
  char      *search_value = NULL;
231
232
  while ((c = getopt (argc, argv, "m:f:")) != EOF)
233
    switch (c) {
234
    case 'f':
235
      file = optarg;
236
      break;
237
    case 'm':
238
    {
239
      int mask = strtoul (optarg, &tmp, 0);
240
      if (*tmp) {
241
        fprintf(stderr, "Invalid debug mask: %s\n",
242
          optarg);
243
        exit(1);
244
      }
245
      blkid_init_debug(mask);
246
      break;
247
    }
248
    case '?':
249
      usage(argv[0]);
250
    }
251
  if (argc >= optind+2) {
252
    search_type = argv[optind];
253
    search_value = argv[optind+1];
254
    optind += 2;
255
  }
256
  if (argc != optind)
257
    usage(argv[0]);
258
259
  if ((ret = blkid_get_cache(&cache, file)) != 0) {
260
    fprintf(stderr, "%s: error creating cache (%d)\n",
261
      argv[0], ret);
262
    exit(1);
263
  }
264
265
  iter = blkid_dev_iterate_begin(cache);
266
  if (search_type)
267
    blkid_dev_set_search(iter, search_type, search_value);
268
  while (blkid_dev_next(iter, &dev) == 0) {
269
    printf("Device: %s\n", blkid_dev_devname(dev));
270
  }
271
  blkid_dev_iterate_end(iter);
272
273
274
  blkid_put_cache(cache);
275
  return (0);
276
}
277
#endif