]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/devname.c
2 * devname.c - get a dev by its device inode name
4 * Copyright (C) Andries Brouwer
5 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
6 * Copyright (C) 2001 Andreas Dilger
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
29 #ifdef HAVE_SYS_STAT_H
39 #include "canonicalize.h" /* $(top_srcdir)/include */
40 #include "pathnames.h"
45 * Find a dev struct in the cache by device name, if available.
47 * If there is no entry with the specified device name, and the create
48 * flag is set, then create an empty device entry.
50 blkid_dev
blkid_get_dev(blkid_cache cache
, const char *devname
, int flags
)
52 blkid_dev dev
= NULL
, tmp
;
53 struct list_head
*p
, *pnext
;
55 if (!cache
|| !devname
)
58 list_for_each(p
, &cache
->bic_devs
) {
59 tmp
= list_entry(p
, struct blkid_struct_dev
, bid_devs
);
60 if (strcmp(tmp
->bid_name
, devname
))
64 printf("found devname %s in cache\n", tmp
->bid_name
));
69 if (!dev
&& (flags
& BLKID_DEV_CREATE
)) {
70 if (access(devname
, F_OK
) < 0)
72 dev
= blkid_new_dev();
75 dev
->bid_time
= INT_MIN
;
76 dev
->bid_name
= strdup(devname
);
77 dev
->bid_cache
= cache
;
78 list_add_tail(&dev
->bid_devs
, &cache
->bic_devs
);
79 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
82 if (flags
& BLKID_DEV_VERIFY
) {
83 dev
= blkid_verify(cache
, dev
);
84 if (!dev
|| !(dev
->bid_flags
& BLKID_BID_FL_VERIFIED
))
87 * If the device is verified, then search the blkid
88 * cache for any entries that match on the type, uuid,
89 * and label, and verify them; if a cache entry can
90 * not be verified, then it's stale and so we remove
93 list_for_each_safe(p
, pnext
, &cache
->bic_devs
) {
94 blkid_dev dev2
= list_entry(p
, struct blkid_struct_dev
, bid_devs
);
95 if (dev2
->bid_flags
& BLKID_BID_FL_VERIFIED
)
97 if (!dev
->bid_type
|| !dev2
->bid_type
||
98 strcmp(dev
->bid_type
, dev2
->bid_type
))
100 if (dev
->bid_label
&& dev2
->bid_label
&&
101 strcmp(dev
->bid_label
, dev2
->bid_label
))
103 if (dev
->bid_uuid
&& dev2
->bid_uuid
&&
104 strcmp(dev
->bid_uuid
, dev2
->bid_uuid
))
106 if ((dev
->bid_label
&& !dev2
->bid_label
) ||
107 (!dev
->bid_label
&& dev2
->bid_label
) ||
108 (dev
->bid_uuid
&& !dev2
->bid_uuid
) ||
109 (!dev
->bid_uuid
&& dev2
->bid_uuid
))
111 dev2
= blkid_verify(cache
, dev2
);
112 if (dev2
&& !(dev2
->bid_flags
& BLKID_BID_FL_VERIFIED
))
113 blkid_free_dev(dev2
);
119 /* Directories where we will try to search for device names */
120 static const char *dirlist
[] = { "/dev", "/devfs", "/devices", NULL
};
122 static int is_dm_leaf(const char *devname
)
124 struct dirent
*de
, *d_de
;
129 if ((dir
= opendir("/sys/block")) == NULL
)
131 while ((de
= readdir(dir
)) != NULL
) {
132 if (!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, "..") ||
133 !strcmp(de
->d_name
, devname
) ||
134 strncmp(de
->d_name
, "dm-", 3) ||
135 strlen(de
->d_name
) > sizeof(path
)-32)
137 sprintf(path
, "/sys/block/%s/slaves", de
->d_name
);
138 if ((d_dir
= opendir(path
)) == NULL
)
140 while ((d_de
= readdir(d_dir
)) != NULL
) {
141 if (!strcmp(d_de
->d_name
, devname
)) {
155 * Probe a single block device to add to the device cache.
157 static void probe_one(blkid_cache cache
, const char *ptname
,
158 dev_t devno
, int pri
, int only_if_new
, int removable
)
160 blkid_dev dev
= NULL
;
161 struct list_head
*p
, *pnext
;
163 char *devname
= NULL
;
165 /* See if we already have this device number in the cache. */
166 list_for_each_safe(p
, pnext
, &cache
->bic_devs
) {
167 blkid_dev tmp
= list_entry(p
, struct blkid_struct_dev
,
169 if (tmp
->bid_devno
== devno
) {
170 if (only_if_new
&& !access(tmp
->bid_name
, F_OK
))
172 dev
= blkid_verify(cache
, tmp
);
173 if (dev
&& (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
))
178 if (dev
&& dev
->bid_devno
== devno
)
181 /* Try to translate private device-mapper dm-<N> names
182 * to standard /dev/mapper/<name>.
184 if (!strncmp(ptname
, "dm-", 3) && isdigit(ptname
[3])) {
185 devname
= canonicalize_dm_name(ptname
);
187 blkid__scan_dir("/dev/mapper", devno
, 0, &devname
);
193 * Take a quick look at /dev/ptname for the device number. We check
194 * all of the likely device directories. If we don't find it, or if
195 * the stat information doesn't check out, use blkid_devno_to_devname()
196 * to find it via an exhaustive search for the device major/minor.
198 for (dir
= dirlist
; *dir
; dir
++) {
202 sprintf(device
, "%s/%s", *dir
, ptname
);
203 if ((dev
= blkid_get_dev(cache
, device
, BLKID_DEV_FIND
)) &&
204 dev
->bid_devno
== devno
)
207 if (stat(device
, &st
) == 0 &&
208 (S_ISBLK(st
.st_mode
) ||
209 (S_ISCHR(st
.st_mode
) && !strncmp(ptname
, "ubi", 3))) &&
210 st
.st_rdev
== devno
) {
211 devname
= strdup(device
);
215 /* Do a short-cut scan of /dev/mapper first */
217 blkid__scan_dir("/dev/mapper", devno
, 0, &devname
);
219 devname
= blkid_devno_to_devname(devno
);
225 dev
= blkid_get_dev(cache
, devname
, BLKID_DEV_NORMAL
);
232 else if (!strncmp(dev
->bid_name
, "/dev/mapper/", 11)) {
233 dev
->bid_pri
= BLKID_PRI_DM
;
234 if (is_dm_leaf(ptname
))
236 } else if (!strncmp(ptname
, "md", 2))
237 dev
->bid_pri
= BLKID_PRI_MD
;
239 dev
->bid_flags
|= BLKID_BID_FL_REMOVABLE
;
244 #define PROC_PARTITIONS "/proc/partitions"
245 #define VG_DIR "/proc/lvm/VGs"
248 * This function initializes the UUID cache with devices from the LVM
249 * proc hierarchy. We currently depend on the names of the LVM
250 * hierarchy giving us the device structure in /dev. (XXX is this a
254 static dev_t
lvm_get_devno(const char *lvm_device
)
261 DBG(DEBUG_DEVNAME
, printf("opening %s\n", lvm_device
));
262 if ((lvf
= fopen(lvm_device
, "r")) == NULL
) {
263 DBG(DEBUG_DEVNAME
, printf("%s: (%d) %m\n", lvm_device
, errno
));
267 while (fgets(buf
, sizeof(buf
), lvf
)) {
268 if (sscanf(buf
, "device: %d:%d", &ma
, &mi
) == 2) {
269 ret
= makedev(ma
, mi
);
278 static void lvm_probe_all(blkid_cache cache
, int only_if_new
)
281 struct dirent
*vg_iter
;
282 int vg_len
= strlen(VG_DIR
);
285 if ((vg_list
= opendir(VG_DIR
)) == NULL
)
288 DBG(DEBUG_DEVNAME
, printf("probing LVM devices under %s\n", VG_DIR
));
290 while ((vg_iter
= readdir(vg_list
)) != NULL
) {
294 struct dirent
*lv_iter
;
296 vg_name
= vg_iter
->d_name
;
297 if (!strcmp(vg_name
, ".") || !strcmp(vg_name
, ".."))
299 vdirname
= malloc(vg_len
+ strlen(vg_name
) + 8);
302 sprintf(vdirname
, "%s/%s/LVs", VG_DIR
, vg_name
);
304 lv_list
= opendir(vdirname
);
309 while ((lv_iter
= readdir(lv_list
)) != NULL
) {
310 char *lv_name
, *lvm_device
;
312 lv_name
= lv_iter
->d_name
;
313 if (!strcmp(lv_name
, ".") || !strcmp(lv_name
, ".."))
316 lvm_device
= malloc(vg_len
+ strlen(vg_name
) +
317 strlen(lv_name
) + 8);
322 sprintf(lvm_device
, "%s/%s/LVs/%s", VG_DIR
, vg_name
,
324 dev
= lvm_get_devno(lvm_device
);
325 sprintf(lvm_device
, "%s/%s", vg_name
, lv_name
);
326 DBG(DEBUG_DEVNAME
, printf("LVM dev %s: devno 0x%04X\n",
328 (unsigned int) dev
));
329 probe_one(cache
, lvm_device
, dev
, BLKID_PRI_LVM
,
340 #define PROC_EVMS_VOLUMES "/proc/evms/volumes"
343 evms_probe_all(blkid_cache cache
, int only_if_new
)
346 int ma
, mi
, sz
, num
= 0;
350 procpt
= fopen(PROC_EVMS_VOLUMES
, "r");
353 while (fgets(line
, sizeof(line
), procpt
)) {
354 if (sscanf (line
, " %d %d %d %*s %*s %[^\n ]",
355 &ma
, &mi
, &sz
, device
) != 4)
358 DBG(DEBUG_DEVNAME
, printf("Checking partition %s (%d, %d)\n",
361 probe_one(cache
, device
, makedev(ma
, mi
), BLKID_PRI_EVMS
,
370 ubi_probe_all(blkid_cache cache
, int only_if_new
)
372 const char **dirname
;
374 for (dirname
= dirlist
; *dirname
; dirname
++) {
375 DBG(DEBUG_DEVNAME
, printf("probing UBI volumes under %s\n",
381 dir
= opendir(*dirname
);
385 while ((iter
= readdir(dir
)) != NULL
) {
391 #ifdef _DIRENT_HAVE_D_TYPE
392 if (iter
->d_type
!= DT_UNKNOWN
&&
393 iter
->d_type
!= DT_CHR
&& iter
->d_type
!= DT_LNK
)
396 if (!strcmp(name
, ".") || !strcmp(name
, "..") ||
397 !strstr(name
, "ubi"))
399 if (!strcmp(name
, "ubi_ctrl"))
401 if (fstat_at(dirfd(dir
), *dirname
, name
, &st
, 0))
406 if (!S_ISCHR(st
.st_mode
) || !minor(dev
))
408 DBG(DEBUG_DEVNAME
, printf("UBI vol %s/%s: devno 0x%04X\n",
409 *dirname
, name
, (int) dev
));
410 probe_one(cache
, name
, dev
, BLKID_PRI_UBI
, only_if_new
, 0);
417 * Read the device data for all available block devices in the system.
419 static int probe_all(blkid_cache cache
, int only_if_new
)
423 char ptname0
[128 + 1], ptname1
[128 + 1], *ptname
= 0;
427 unsigned long long sz
;
428 int lens
[2] = { 0, 0 };
429 int which
= 0, last
= 0;
430 struct list_head
*p
, *pnext
;
432 ptnames
[0] = ptname0
;
433 ptnames
[1] = ptname1
;
436 return -BLKID_ERR_PARAM
;
438 if (cache
->bic_flags
& BLKID_BIC_FL_PROBED
&&
439 time(0) - cache
->bic_time
< BLKID_PROBE_INTERVAL
)
442 blkid_read_cache(cache
);
443 evms_probe_all(cache
, only_if_new
);
445 lvm_probe_all(cache
, only_if_new
);
447 ubi_probe_all(cache
, only_if_new
);
449 proc
= fopen(PROC_PARTITIONS
, "r");
451 return -BLKID_ERR_PROC
;
453 while (fgets(line
, sizeof(line
), proc
)) {
456 ptname
= ptnames
[which
];
458 if (sscanf(line
, " %d %d %llu %128[^\n ]",
459 &ma
, &mi
, &sz
, ptname
) != 4)
461 devs
[which
] = makedev(ma
, mi
);
463 DBG(DEBUG_DEVNAME
, printf("read partition name %s\n", ptname
));
465 /* Skip whole disk devs unless they have no partitions.
466 * If base name of device has changed, also
467 * check previous dev to see if it didn't have a partn.
468 * heuristic: partition name ends in a digit, & partition
469 * names contain whole device name as substring.
471 * Skip extended partitions.
472 * heuristic: size is 1
474 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
477 lens
[which
] = strlen(ptname
);
479 /* ends in a digit, clearly a partition, so check */
480 if (isdigit(ptname
[lens
[which
] - 1])) {
482 printf("partition dev %s, devno 0x%04X\n",
483 ptname
, (unsigned int) devs
[which
]));
486 probe_one(cache
, ptname
, devs
[which
], 0,
488 lens
[which
] = 0; /* mark as checked */
492 * If last was a whole disk and we just found a partition
493 * on it, remove the whole-disk dev from the cache if
496 if (lens
[last
] && !strncmp(ptnames
[last
], ptname
, lens
[last
])) {
497 list_for_each_safe(p
, pnext
, &cache
->bic_devs
) {
500 /* find blkid dev for the whole-disk devno */
501 tmp
= list_entry(p
, struct blkid_struct_dev
,
503 if (tmp
->bid_devno
== devs
[last
]) {
505 printf("freeing %s\n",
508 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
515 * If last was not checked because it looked like a whole-disk
516 * dev, and the device's base name has changed,
517 * check last as well.
519 if (lens
[last
] && strncmp(ptnames
[last
], ptname
, lens
[last
])) {
521 printf("whole dev %s, devno 0x%04X\n",
522 ptnames
[last
], (unsigned int) devs
[last
]));
523 probe_one(cache
, ptnames
[last
], devs
[last
], 0,
529 /* Handle the last device if it wasn't partitioned */
531 probe_one(cache
, ptname
, devs
[which
], 0, only_if_new
, 0);
534 blkid_flush_cache(cache
);
538 /* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...)
540 static int probe_all_removable(blkid_cache cache
)
546 return -BLKID_ERR_PARAM
;
548 dir
= opendir(_PATH_SYS_BLOCK
);
550 return -BLKID_ERR_PROC
;
552 while((d
= readdir(dir
))) {
553 struct sysfs_cxt sysfs
= UL_SYSFSCXT_EMPTY
;
557 #ifdef _DIRENT_HAVE_D_TYPE
558 if (d
->d_type
!= DT_UNKNOWN
&& d
->d_type
!= DT_LNK
)
561 if (d
->d_name
[0] == '.' &&
562 ((d
->d_name
[1] == 0) ||
563 ((d
->d_name
[1] == '.') && (d
->d_name
[2] == 0))))
566 devno
= sysfs_devname_to_devno(d
->d_name
, NULL
);
570 if (sysfs_init(&sysfs
, devno
, NULL
) == 0) {
571 sysfs_read_int(&sysfs
, "removable", &removable
);
572 sysfs_deinit(&sysfs
);
576 probe_one(cache
, d
->d_name
, devno
, 0, 0, 1);
586 * @cache: cache handler
588 * Probes all block devices.
590 * Returns: 0 on success, or number less than zero in case of error.
592 int blkid_probe_all(blkid_cache cache
)
596 DBG(DEBUG_PROBE
, printf("Begin blkid_probe_all()\n"));
597 ret
= probe_all(cache
, 0);
598 cache
->bic_time
= time(0);
599 cache
->bic_flags
|= BLKID_BIC_FL_PROBED
;
600 DBG(DEBUG_PROBE
, printf("End blkid_probe_all()\n"));
605 * blkid_probe_all_new:
606 * @cache: cache handler
608 * Probes all new block devices.
610 * Returns: 0 on success, or number less than zero in case of error.
612 int blkid_probe_all_new(blkid_cache cache
)
616 DBG(DEBUG_PROBE
, printf("Begin blkid_probe_all_new()\n"));
617 ret
= probe_all(cache
, 1);
618 DBG(DEBUG_PROBE
, printf("End blkid_probe_all_new()\n"));
623 * blkid_probe_all_removable:
624 * @cache: cache handler
626 * The libblkid probing is based on devices from /proc/partitions by default.
627 * This file usually does not contain removable devices (e.g. CDROMs) and this kind
628 * of devices are invisible for libblkid.
630 * This function adds removable block devices to @cache (probing is based on
631 * information from the /sys directory). Don't forget that removable devices
632 * (floppies, CDROMs, ...) could be pretty slow. It's very bad idea to call
633 * this function by default.
635 * Note that devices which were detected by this function won't be written to
636 * blkid.tab cache file.
638 * Returns: 0 on success, or number less than zero in case of error.
640 int blkid_probe_all_removable(blkid_cache cache
)
644 DBG(DEBUG_PROBE
, printf("Begin blkid_probe_all_removable()\n"));
645 ret
= probe_all_removable(cache
);
646 DBG(DEBUG_PROBE
, printf("End blkid_probe_all_removable()\n"));
651 int main(int argc
, char **argv
)
653 blkid_cache cache
= NULL
;
656 blkid_init_debug(DEBUG_ALL
);
658 fprintf(stderr
, "Usage: %s\n"
659 "Probe all devices and exit\n", argv
[0]);
662 if ((ret
= blkid_get_cache(&cache
, "/dev/null")) != 0) {
663 fprintf(stderr
, "%s: error creating cache (%d)\n",
667 if (blkid_probe_all(cache
) < 0)
668 printf("%s: error probing devices\n", argv
[0]);
670 if (blkid_probe_all_removable(cache
) < 0)
671 printf("%s: error probing removable devices\n", argv
[0]);
673 blkid_put_cache(cache
);