devname.c revision 257ace82b77a281da6d0491294eda6f0b27ef424
1d93256e55673a17d18543397ec462416acb13792Douglas Gregor/* 25352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * devname.c - get a dev by its device inode name 35352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * 45352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * Copyright (C) Andries Brouwer 55352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o 65352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * Copyright (C) 2001 Andreas Dilger 75352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * 85352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * %Begin-Header% 95352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * This file may be redistributed under the terms of the 105352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * GNU Lesser General Public License. 115352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * %End-Header% 125352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor */ 135352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor 145352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#define _GNU_SOURCE 1 155352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor 161edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#include <stdio.h> 17153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <string.h> 18153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <limits.h> 191edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#if HAVE_UNISTD_H 205352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#include <unistd.h> 215352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#endif 2235b8440f615a2336f2819a98a78fc89f07d905e1Daniel Dunbar#include <stdlib.h> 23b846debc1b22a37228efe4aa87b34482d15b6a3cBenjamin Kramer#include <string.h> 24153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <ctype.h> 25153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#if HAVE_SYS_TYPES_H 26153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <sys/types.h> 27153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#endif 28153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#if HAVE_SYS_STAT_H 29153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <sys/stat.h> 30153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#endif 31153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#if HAVE_ERRNO_H 32153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <errno.h> 33153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#endif 34153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#if HAVE_SYS_MKDEV_H 35153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <sys/mkdev.h> 36153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#endif 37153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <time.h> 38153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 39153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "blkidP.h" 40153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 41153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#ifdef HAVE_DEVMAPPER 42153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <libdevmapper.h> 43153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#endif 44153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 45153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek/* 46153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek * Find a dev struct in the cache by device name, if available. 47153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek * 48153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek * If there is no entry with the specified device name, and the create 49153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek * flag is set, then create an empty device entry. 50153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek */ 51153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekblkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) 52153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek{ 53153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek blkid_dev dev = NULL, tmp; 544914612675787cda11ad6b31735e130a81a1d7a1Daniel Dunbar struct list_head *p; 551edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 561edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (!cache || !devname) 577473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek return NULL; 587473b1c6e7ba2654d4a0d469198f0e01b485b51aTed Kremenek 591edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek list_for_each(p, &cache->bic_devs) { 601edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek tmp = list_entry(p, struct blkid_struct_dev, bid_devs); 611edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (strcmp(tmp->bid_name, devname)) 621edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek continue; 631edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 641edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek DBG(DEBUG_DEVNAME, 651edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek printf("found devname %s in cache\n", tmp->bid_name)); 661edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev = tmp; 671edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek break; 681edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek } 691edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 701edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (!dev && (flags & BLKID_DEV_CREATE)) { 711edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev = blkid_new_dev(); 721edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (!dev) 731edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek return NULL; 741edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev->bid_time = INT_MIN; 751edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev->bid_name = blkid_strdup(devname); 7678d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek dev->bid_cache = cache; 7778d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek list_add_tail(&dev->bid_devs, &cache->bic_devs); 7878d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek cache->bic_flags |= BLKID_BIC_FL_CHANGED; 7978d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek } 801edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 811edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (flags & BLKID_DEV_VERIFY) 821edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev = blkid_verify(cache, dev); 831edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek return dev; 841edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek} 851edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 861edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#ifdef HAVE_DEVMAPPER 871edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenekstatic int dm_device_is_leaf(const dev_t dev); 881edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#endif 891edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 901edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek/* 911edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek * Probe a single block device to add to the device cache. 921edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek */ 931edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenekstatic void probe_one(blkid_cache cache, const char *ptname, 94153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek dev_t devno, int pri, int only_if_new) 95153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek{ 96153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek blkid_dev dev = NULL; 97153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek struct list_head *p; 98153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek const char **dir; 991edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek char *devname = NULL; 1001edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 101153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek /* See if we already have this device number in the cache. */ 102153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek list_for_each(p, &cache->bic_devs) { 103153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek blkid_dev tmp = list_entry(p, struct blkid_struct_dev, 104153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek bid_devs); 105153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#ifdef HAVE_DEVMAPPER 1061edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (!dm_device_is_leaf(devno)) 1071edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek continue; 1081edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#endif 1091edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (tmp->bid_devno == devno) { 1101edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (only_if_new) 111a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return; 1121edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev = blkid_verify(cache, tmp); 113a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor break; 114a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 115a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 116a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (dev && dev->bid_devno == devno) 117a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor goto set_pri; 1181edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 1191edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek /* 1201edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek * Take a quick look at /dev/ptname for the device number. We check 1211edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek * all of the likely device directories. If we don't find it, or if 1221edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek * the stat information doesn't check out, use blkid_devno_to_devname() 1231edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek * to find it via an exhaustive search for the device major/minor. 124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines */ 125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (dir = blkid_devdirs; *dir; dir++) { 1261edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek struct stat st; 127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines char device[256]; 1281edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 1291edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek sprintf(device, "%s/%s", *dir, ptname); 130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && 1311edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek dev->bid_devno == devno) 1321edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek goto set_pri; 133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && 1351edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek st.st_rdev == devno) { 136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines devname = blkid_strdup(device); 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 13878d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek } 139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 14078d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek if (!devname) { 1411edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek devname = blkid_devno_to_devname(devno); 142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!devname) 143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1441edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek } 145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); 1461edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek free(devname); 1471edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesset_pri: 1491edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek if (!pri && !strncmp(ptname, "md", 2)) 1501edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek pri = BLKID_PRI_MD; 151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (dev) 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines dev->bid_pri = pri; 1531edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek return; 1541edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek} 1551edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek 1561edabbc32a07654d9b9fe44f50533ff146abd03eTed Kremenek#ifdef HAVE_DEVMAPPER 1575352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregorstatic void dm_quiet_log(int level, const char *file, int line, 158d93256e55673a17d18543397ec462416acb13792Douglas Gregor const char *f, ...) 159996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis{ 160996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis return; 161996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis} 162996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis 163996e6e564af7483e2d5e0b70df5fdb9f79ec4b5aArgyrios Kyrtzidis/* 1645352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor * device-mapper support 1655352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor */ 1665352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregorstatic int dm_device_has_dep(const dev_t dev, const char *name) 167{ 168 struct dm_task *task; 169 struct dm_deps *deps; 170 struct dm_info info; 171 int i; 172 173 task = dm_task_create(DM_DEVICE_DEPS); 174 if (!task) 175 return 0; 176 177 dm_task_set_name(task, name); 178 dm_task_run(task); 179 dm_task_get_info(task, &info); 180 181 if (!info.exists) { 182 dm_task_destroy(task); 183 return 0; 184 } 185 186 deps = dm_task_get_deps(task); 187 if (!deps || deps->count == 0) { 188 dm_task_destroy(task); 189 return 0; 190 } 191 192 for (i = 0; i < deps->count; i++) { 193 dev_t dep_dev = deps->device[i]; 194 195 if (dev == dep_dev) { 196 dm_task_destroy(task); 197 return 1; 198 } 199 } 200 201 dm_task_destroy(task); 202 return 0; 203} 204 205static int dm_device_is_leaf(const dev_t dev) 206{ 207 struct dm_task *task; 208 struct dm_names *names; 209 unsigned int next = 0; 210 int n, ret = 1; 211 212 dm_log_init(dm_quiet_log); 213 task = dm_task_create(DM_DEVICE_LIST); 214 if (!task) 215 return 1; 216 dm_log_init(0); 217 218 dm_task_run(task); 219 names = dm_task_get_names(task); 220 if (!names || !names->dev) { 221 dm_task_destroy(task); 222 return 1; 223 } 224 225 n = 0; 226 do { 227 names = (void *)names + next; 228 229 if (dm_device_has_dep(dev, names->name)) 230 ret = 0; 231 232 next = names->next; 233 } while (next); 234 235 dm_task_destroy(task); 236 237 return ret; 238} 239 240static dev_t dm_get_devno(const char *name) 241{ 242 struct dm_task *task; 243 struct dm_info info; 244 dev_t ret = 0; 245 246 task = dm_task_create(DM_DEVICE_INFO); 247 if (!task) 248 return ret; 249 250 dm_task_set_name(task, name); 251 dm_task_run(task); 252 dm_task_get_info(task, &info); 253 254 if (!info.exists) { 255 dm_task_destroy(task); 256 return ret; 257 } 258 259 ret = makedev(info.major, info.minor); 260 261 dm_task_destroy(task); 262 263 return ret; 264} 265 266static void dm_probe_all(blkid_cache cache, int only_if_new) 267{ 268 struct dm_task *task; 269 struct dm_names *names; 270 unsigned int next = 0; 271 int n; 272 273 dm_log_init(dm_quiet_log); 274 task = dm_task_create(DM_DEVICE_LIST); 275 if (!task) 276 return; 277 dm_log_init(0); 278 279 dm_task_run(task); 280 names = dm_task_get_names(task); 281 if (!names || !names->dev) { 282 dm_task_destroy(task); 283 return; 284 } 285 286 n = 0; 287 do { 288 int rc; 289 char *device = NULL; 290 dev_t dev = 0; 291 292 names = (void *)names + next; 293 294 rc = asprintf(&device, "mapper/%s", names->name); 295 if (rc < 0) 296 goto try_next; 297 298 dev = dm_get_devno(names->name); 299 if (dev == 0) 300 goto try_next; 301 302 if (!dm_device_is_leaf(dev)) 303 goto try_next; 304 305 probe_one(cache, device, dev, BLKID_PRI_DM, only_if_new); 306 307try_next: 308 free(device); 309 next = names->next; 310 } while (next); 311 312 dm_task_destroy(task); 313} 314#endif /* HAVE_DEVMAPPER */ 315 316#define PROC_PARTITIONS "/proc/partitions" 317#define VG_DIR "/proc/lvm/VGs" 318 319/* 320 * This function initializes the UUID cache with devices from the LVM 321 * proc hierarchy. We currently depend on the names of the LVM 322 * hierarchy giving us the device structure in /dev. (XXX is this a 323 * safe thing to do?) 324 */ 325#ifdef VG_DIR 326#include <dirent.h> 327static dev_t lvm_get_devno(const char *lvm_device) 328{ 329 FILE *lvf; 330 char buf[1024]; 331 int ma, mi; 332 dev_t ret = 0; 333 334 DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); 335 if ((lvf = fopen(lvm_device, "r")) == NULL) { 336 DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, 337 strerror(errno))); 338 return 0; 339 } 340 341 while (fgets(buf, sizeof(buf), lvf)) { 342 if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { 343 ret = makedev(ma, mi); 344 break; 345 } 346 } 347 fclose(lvf); 348 349 return ret; 350} 351 352static void lvm_probe_all(blkid_cache cache, int only_if_new) 353{ 354 DIR *vg_list; 355 struct dirent *vg_iter; 356 int vg_len = strlen(VG_DIR); 357 dev_t dev; 358 359 if ((vg_list = opendir(VG_DIR)) == NULL) 360 return; 361 362 DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); 363 364 while ((vg_iter = readdir(vg_list)) != NULL) { 365 DIR *lv_list; 366 char *vdirname; 367 char *vg_name; 368 struct dirent *lv_iter; 369 370 vg_name = vg_iter->d_name; 371 if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) 372 continue; 373 vdirname = malloc(vg_len + strlen(vg_name) + 8); 374 if (!vdirname) 375 goto exit; 376 sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); 377 378 lv_list = opendir(vdirname); 379 free(vdirname); 380 if (lv_list == NULL) 381 continue; 382 383 while ((lv_iter = readdir(lv_list)) != NULL) { 384 char *lv_name, *lvm_device; 385 386 lv_name = lv_iter->d_name; 387 if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) 388 continue; 389 390 lvm_device = malloc(vg_len + strlen(vg_name) + 391 strlen(lv_name) + 8); 392 if (!lvm_device) { 393 closedir(lv_list); 394 goto exit; 395 } 396 sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, 397 lv_name); 398 dev = lvm_get_devno(lvm_device); 399 sprintf(lvm_device, "%s/%s", vg_name, lv_name); 400 DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", 401 lvm_device, 402 (unsigned int) dev)); 403 probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, 404 only_if_new); 405 free(lvm_device); 406 } 407 closedir(lv_list); 408 } 409exit: 410 closedir(vg_list); 411} 412#endif 413 414#define PROC_EVMS_VOLUMES "/proc/evms/volumes" 415 416static int 417evms_probe_all(blkid_cache cache, int only_if_new) 418{ 419 char line[100]; 420 int ma, mi, sz, num = 0; 421 FILE *procpt; 422 char device[110]; 423 424 procpt = fopen(PROC_EVMS_VOLUMES, "r"); 425 if (!procpt) 426 return 0; 427 while (fgets(line, sizeof(line), procpt)) { 428 if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", 429 &ma, &mi, &sz, device) != 4) 430 continue; 431 432 DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", 433 device, ma, mi)); 434 435 probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, 436 only_if_new); 437 num++; 438 } 439 fclose(procpt); 440 return num; 441} 442 443/* 444 * Read the device data for all available block devices in the system. 445 */ 446static int probe_all(blkid_cache cache, int only_if_new) 447{ 448 FILE *proc; 449 char line[1024]; 450 char ptname0[128], ptname1[128], *ptname = 0; 451 char *ptnames[2]; 452 dev_t devs[2]; 453 int ma, mi; 454 unsigned long long sz; 455 int lens[2] = { 0, 0 }; 456 int which = 0, last = 0; 457 458 ptnames[0] = ptname0; 459 ptnames[1] = ptname1; 460 461 if (!cache) 462 return -BLKID_ERR_PARAM; 463 464 if (cache->bic_flags & BLKID_BIC_FL_PROBED && 465 time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) 466 return 0; 467 468 blkid_read_cache(cache); 469#ifdef HAVE_DEVMAPPER 470 dm_probe_all(cache, only_if_new); 471#endif 472 evms_probe_all(cache, only_if_new); 473#ifdef VG_DIR 474 lvm_probe_all(cache, only_if_new); 475#endif 476 477 proc = fopen(PROC_PARTITIONS, "r"); 478 if (!proc) 479 return -BLKID_ERR_PROC; 480 481 while (fgets(line, sizeof(line), proc)) { 482 last = which; 483 which ^= 1; 484 ptname = ptnames[which]; 485 486 if (sscanf(line, " %d %d %llu %128[^\n ]", 487 &ma, &mi, &sz, ptname) != 4) 488 continue; 489 devs[which] = makedev(ma, mi); 490 491 DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); 492 493 /* Skip whole disk devs unless they have no partitions 494 * If we don't have a partition on this dev, also 495 * check previous dev to see if it didn't have a partn. 496 * heuristic: partition name ends in a digit. 497 * 498 * Skip extended partitions. 499 * heuristic: size is 1 500 * 501 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs 502 */ 503 504 lens[which] = strlen(ptname); 505 if (isdigit(ptname[lens[which] - 1])) { 506 DBG(DEBUG_DEVNAME, 507 printf("partition dev %s, devno 0x%04X\n", 508 ptname, (unsigned int) devs[which])); 509 510 if (sz > 1) 511 probe_one(cache, ptname, devs[which], 0, 512 only_if_new); 513 lens[which] = 0; 514 lens[last] = 0; 515 } else if (lens[last] && strncmp(ptnames[last], ptname, 516 lens[last])) { 517 DBG(DEBUG_DEVNAME, 518 printf("whole dev %s, devno 0x%04X\n", 519 ptnames[last], (unsigned int) devs[last])); 520 probe_one(cache, ptnames[last], devs[last], 0, 521 only_if_new); 522 lens[last] = 0; 523 } 524 } 525 526 /* Handle the last device if it wasn't partitioned */ 527 if (lens[which]) 528 probe_one(cache, ptname, devs[which], 0, only_if_new); 529 530 fclose(proc); 531 blkid_flush_cache(cache); 532 return 0; 533} 534 535int blkid_probe_all(blkid_cache cache) 536{ 537 int ret; 538 539 DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n")); 540 ret = probe_all(cache, 0); 541 cache->bic_time = time(0); 542 cache->bic_flags |= BLKID_BIC_FL_PROBED; 543 DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n")); 544 return ret; 545} 546 547int blkid_probe_all_new(blkid_cache cache) 548{ 549 int ret; 550 551 DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n")); 552 ret = probe_all(cache, 1); 553 DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n")); 554 return ret; 555} 556 557 558#ifdef TEST_PROGRAM 559int main(int argc, char **argv) 560{ 561 blkid_cache cache = NULL; 562 int ret; 563 564 blkid_debug_mask = DEBUG_ALL; 565 if (argc != 1) { 566 fprintf(stderr, "Usage: %s\n" 567 "Probe all devices and exit\n", argv[0]); 568 exit(1); 569 } 570 if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { 571 fprintf(stderr, "%s: error creating cache (%d)\n", 572 argv[0], ret); 573 exit(1); 574 } 575 if (blkid_probe_all(cache) < 0) 576 printf("%s: error probing devices\n", argv[0]); 577 578 blkid_put_cache(cache); 579 return (0); 580} 581#endif 582