L4Re/departure

Annotated libext2fs/lib/libblkid/devname.c

212:c0651b3b711f
2021-10-09 Paul Boddie Updated libext2fs to version 1.46.2, also introducing some notes about the process of adapting the library for L4Re, together with a tool to generate a configuration from an existing, external "host" build of the library.
paul@181 1
/*
paul@181 2
 * devname.c - get a dev by its device inode name
paul@181 3
 *
paul@181 4
 * Copyright (C) Andries Brouwer
paul@181 5
 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
paul@181 6
 * Copyright (C) 2001 Andreas Dilger
paul@181 7
 *
paul@181 8
 * %Begin-Header%
paul@181 9
 * This file may be redistributed under the terms of the
paul@181 10
 * GNU Lesser General Public License.
paul@181 11
 * %End-Header%
paul@181 12
 */
paul@181 13
paul@181 14
#define _GNU_SOURCE 1
paul@181 15
paul@181 16
#include "config.h"
paul@181 17
#include <stdio.h>
paul@181 18
#include <string.h>
paul@181 19
#include <limits.h>
paul@181 20
#if HAVE_UNISTD_H
paul@181 21
#include <unistd.h>
paul@181 22
#endif
paul@181 23
#include <stdlib.h>
paul@181 24
#include <string.h>
paul@181 25
#include <ctype.h>
paul@181 26
#if HAVE_SYS_TYPES_H
paul@181 27
#include <sys/types.h>
paul@181 28
#endif
paul@181 29
#include <dirent.h>
paul@181 30
#if HAVE_SYS_STAT_H
paul@181 31
#include <sys/stat.h>
paul@181 32
#endif
paul@181 33
#if HAVE_ERRNO_H
paul@181 34
#include <errno.h>
paul@181 35
#endif
paul@181 36
#if HAVE_SYS_MKDEV_H
paul@181 37
#include <sys/mkdev.h>
paul@181 38
#endif
paul@181 39
#ifdef HAVE_SYS_SYSMACROS_H
paul@181 40
#include <sys/sysmacros.h>
paul@181 41
#endif
paul@181 42
#include <time.h>
paul@181 43
paul@181 44
#include "blkidP.h"
paul@181 45
paul@181 46
/*
paul@181 47
 * Find a dev struct in the cache by device name, if available.
paul@181 48
 *
paul@181 49
 * If there is no entry with the specified device name, and the create
paul@181 50
 * flag is set, then create an empty device entry.
paul@181 51
 */
paul@181 52
blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
paul@181 53
{
paul@181 54
	blkid_dev dev = NULL, tmp;
paul@181 55
	struct list_head *p, *pnext;
paul@181 56
paul@181 57
	if (!cache || !devname)
paul@181 58
		return NULL;
paul@181 59
paul@181 60
	list_for_each(p, &cache->bic_devs) {
paul@181 61
		tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
paul@181 62
		if (strcmp(tmp->bid_name, devname))
paul@181 63
			continue;
paul@181 64
paul@181 65
		DBG(DEBUG_DEVNAME,
paul@181 66
		    printf("found devname %s in cache\n", tmp->bid_name));
paul@181 67
		dev = tmp;
paul@181 68
		break;
paul@181 69
	}
paul@181 70
paul@181 71
	if (!dev && (flags & BLKID_DEV_CREATE)) {
paul@181 72
		if (access(devname, F_OK) < 0)
paul@181 73
			return NULL;
paul@181 74
		dev = blkid_new_dev();
paul@181 75
		if (!dev)
paul@181 76
			return NULL;
paul@181 77
		dev->bid_time = INT_MIN;
paul@181 78
		dev->bid_name = blkid_strdup(devname);
paul@181 79
		dev->bid_cache = cache;
paul@181 80
		list_add_tail(&dev->bid_devs, &cache->bic_devs);
paul@181 81
		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
paul@181 82
	}
paul@181 83
paul@181 84
	if (flags & BLKID_DEV_VERIFY) {
paul@181 85
		dev = blkid_verify(cache, dev);
paul@181 86
		if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED))
paul@181 87
			return dev;
paul@181 88
		/*
paul@181 89
		 * If the device is verified, then search the blkid
paul@181 90
		 * cache for any entries that match on the type, uuid,
paul@181 91
		 * and label, and verify them; if a cache entry can
paul@181 92
		 * not be verified, then it's stale and so we remove
paul@181 93
		 * it.
paul@181 94
		 */
paul@181 95
		list_for_each_safe(p, pnext, &cache->bic_devs) {
paul@181 96
			blkid_dev dev2;
paul@181 97
			dev2 = list_entry(p, struct blkid_struct_dev, bid_devs);
paul@181 98
			if (dev2->bid_flags & BLKID_BID_FL_VERIFIED)
paul@181 99
				continue;
paul@181 100
			if (!dev->bid_type || !dev2->bid_type ||
paul@181 101
			    strcmp(dev->bid_type, dev2->bid_type))
paul@181 102
				continue;
paul@181 103
			if (dev->bid_label && dev2->bid_label &&
paul@181 104
			    strcmp(dev->bid_label, dev2->bid_label))
paul@181 105
				continue;
paul@181 106
			if (dev->bid_uuid && dev2->bid_uuid &&
paul@181 107
			    strcmp(dev->bid_uuid, dev2->bid_uuid))
paul@181 108
				continue;
paul@181 109
			if ((dev->bid_label && !dev2->bid_label) ||
paul@181 110
			    (!dev->bid_label && dev2->bid_label) ||
paul@181 111
			    (dev->bid_uuid && !dev2->bid_uuid) ||
paul@181 112
			    (!dev->bid_uuid && dev2->bid_uuid))
paul@181 113
				continue;
paul@181 114
			dev2 = blkid_verify(cache, dev2);
paul@181 115
			if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED))
paul@181 116
				blkid_free_dev(dev2);
paul@181 117
		}
paul@181 118
	}
paul@181 119
	return dev;
paul@181 120
}
paul@181 121
paul@181 122
/* Directories where we will try to search for device names */
paul@181 123
static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL };
paul@181 124
paul@181 125
static int is_dm_leaf(const char *devname)
paul@181 126
{
paul@181 127
	struct dirent	*de, *d_de;
paul@181 128
	DIR		*dir, *d_dir;
paul@212 129
	char		path[300];
paul@181 130
	int		ret = 1;
paul@181 131
paul@181 132
	if ((dir = opendir("/sys/block")) == NULL)
paul@181 133
		return 0;
paul@181 134
	while ((de = readdir(dir)) != NULL) {
paul@181 135
		if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
paul@181 136
		    !strcmp(de->d_name, devname) ||
paul@181 137
		    strncmp(de->d_name, "dm-", 3) ||
paul@181 138
		    strlen(de->d_name) > sizeof(path)-32)
paul@181 139
			continue;
paul@181 140
		sprintf(path, "/sys/block/%s/slaves", de->d_name);
paul@181 141
		if ((d_dir = opendir(path)) == NULL)
paul@181 142
			continue;
paul@181 143
		while ((d_de = readdir(d_dir)) != NULL) {
paul@181 144
			if (!strcmp(d_de->d_name, devname)) {
paul@181 145
				ret = 0;
paul@181 146
				break;
paul@181 147
			}
paul@181 148
		}
paul@181 149
		closedir(d_dir);
paul@181 150
		if (!ret)
paul@181 151
			break;
paul@181 152
	}
paul@181 153
	closedir(dir);
paul@181 154
	return ret;
paul@181 155
}
paul@181 156
paul@181 157
/*
paul@181 158
 * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
paul@181 159
 * provides the real DM device names in /sys/block/<ptname>/dm/name
paul@181 160
 */
paul@181 161
static char *get_dm_name(const char *ptname)
paul@181 162
{
paul@181 163
	FILE	*f;
paul@181 164
	size_t	sz;
paul@212 165
	char	path[300], name[256], *res = NULL;
paul@181 166
paul@181 167
	snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
paul@181 168
	if ((f = fopen(path, "r")) == NULL)
paul@181 169
		return NULL;
paul@181 170
paul@181 171
	/* read "<name>\n" from sysfs */
paul@181 172
	if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
paul@181 173
		name[sz - 1] = '\0';
paul@181 174
		snprintf(path, sizeof(path), "/dev/mapper/%s", name);
paul@181 175
		res = blkid_strdup(path);
paul@181 176
	}
paul@181 177
	fclose(f);
paul@181 178
	return res;
paul@181 179
}
paul@181 180
paul@181 181
/*
paul@181 182
 * Probe a single block device to add to the device cache.
paul@181 183
 */
paul@181 184
static void probe_one(blkid_cache cache, const char *ptname,
paul@181 185
		      dev_t devno, int pri, int only_if_new)
paul@181 186
{
paul@181 187
	blkid_dev dev = NULL;
paul@181 188
	struct list_head *p, *pnext;
paul@181 189
	const char **dir;
paul@181 190
	char *devname = NULL;
paul@181 191
paul@181 192
	/* See if we already have this device number in the cache. */
paul@181 193
	list_for_each_safe(p, pnext, &cache->bic_devs) {
paul@181 194
		blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
paul@181 195
					   bid_devs);
paul@181 196
		if (tmp->bid_devno == devno) {
paul@181 197
			if (only_if_new && !access(tmp->bid_name, F_OK))
paul@181 198
				return;
paul@181 199
			dev = blkid_verify(cache, tmp);
paul@181 200
			if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
paul@181 201
				break;
paul@181 202
			dev = 0;
paul@181 203
		}
paul@181 204
	}
paul@181 205
	if (dev && dev->bid_devno == devno)
paul@181 206
		goto set_pri;
paul@181 207
paul@181 208
	/* Try to translate private device-mapper dm-<N> names
paul@181 209
	 * to standard /dev/mapper/<name>.
paul@181 210
	 */
paul@181 211
	if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) {
paul@181 212
		devname = get_dm_name(ptname);
paul@181 213
		if (!devname)
paul@181 214
			blkid__scan_dir("/dev/mapper", devno, 0, &devname);
paul@181 215
		if (devname)
paul@181 216
			goto get_dev;
paul@181 217
	}
paul@181 218
paul@181 219
	/*
paul@181 220
	 * Take a quick look at /dev/ptname for the device number.  We check
paul@181 221
	 * all of the likely device directories.  If we don't find it, or if
paul@181 222
	 * the stat information doesn't check out, use blkid_devno_to_devname()
paul@181 223
	 * to find it via an exhaustive search for the device major/minor.
paul@181 224
	 */
paul@181 225
	for (dir = dirlist; *dir; dir++) {
paul@181 226
		struct stat st;
paul@181 227
		char device[256];
paul@181 228
paul@181 229
		sprintf(device, "%s/%s", *dir, ptname);
paul@181 230
		if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
paul@181 231
		    dev->bid_devno == devno)
paul@181 232
			goto set_pri;
paul@181 233
paul@181 234
		if (stat(device, &st) == 0 &&
paul@181 235
		    blkidP_is_disk_device(st.st_mode) &&
paul@181 236
		    st.st_rdev == devno) {
paul@181 237
			devname = blkid_strdup(device);
paul@181 238
			goto get_dev;
paul@181 239
		}
paul@181 240
	}
paul@181 241
	/* Do a short-cut scan of /dev/mapper first */
paul@181 242
	if (!devname)
paul@181 243
		devname = get_dm_name(ptname);
paul@181 244
	if (!devname)
paul@181 245
		blkid__scan_dir("/dev/mapper", devno, 0, &devname);
paul@181 246
	if (!devname) {
paul@181 247
		devname = blkid_devno_to_devname(devno);
paul@181 248
		if (!devname)
paul@181 249
			return;
paul@181 250
	}
paul@181 251
get_dev:
paul@181 252
	dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
paul@181 253
	free(devname);
paul@181 254
set_pri:
paul@181 255
	if (dev) {
paul@181 256
		if (pri)
paul@181 257
			dev->bid_pri = pri;
paul@181 258
		else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) {
paul@181 259
			dev->bid_pri = BLKID_PRI_DM;
paul@181 260
			if (is_dm_leaf(ptname))
paul@181 261
				dev->bid_pri += 5;
paul@181 262
		} else if (!strncmp(ptname, "md", 2))
paul@181 263
			dev->bid_pri = BLKID_PRI_MD;
paul@181 264
 	}
paul@181 265
	return;
paul@181 266
}
paul@181 267
paul@181 268
#define PROC_PARTITIONS "/proc/partitions"
paul@181 269
#define VG_DIR		"/proc/lvm/VGs"
paul@181 270
paul@181 271
/*
paul@181 272
 * This function initializes the UUID cache with devices from the LVM
paul@181 273
 * proc hierarchy.  We currently depend on the names of the LVM
paul@181 274
 * hierarchy giving us the device structure in /dev.  (XXX is this a
paul@181 275
 * safe thing to do?)
paul@181 276
 */
paul@181 277
#ifdef VG_DIR
paul@181 278
static dev_t lvm_get_devno(const char *lvm_device)
paul@181 279
{
paul@181 280
	FILE *lvf;
paul@181 281
	char buf[1024];
paul@181 282
	int ma, mi;
paul@181 283
	dev_t ret = 0;
paul@181 284
paul@181 285
	DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
paul@181 286
	if ((lvf = fopen(lvm_device, "r")) == NULL) {
paul@181 287
		DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
paul@181 288
					  strerror(errno)));
paul@181 289
		return 0;
paul@181 290
	}
paul@181 291
paul@181 292
	while (fgets(buf, sizeof(buf), lvf)) {
paul@181 293
		if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
paul@181 294
			ret = makedev(ma, mi);
paul@181 295
			break;
paul@181 296
		}
paul@181 297
	}
paul@181 298
	fclose(lvf);
paul@181 299
paul@181 300
	return ret;
paul@181 301
}
paul@181 302
paul@181 303
static void lvm_probe_all(blkid_cache cache, int only_if_new)
paul@181 304
{
paul@181 305
	DIR		*vg_list;
paul@181 306
	struct dirent	*vg_iter;
paul@181 307
	int		vg_len = strlen(VG_DIR);
paul@181 308
	dev_t		dev;
paul@181 309
paul@181 310
	if ((vg_list = opendir(VG_DIR)) == NULL)
paul@181 311
		return;
paul@181 312
paul@181 313
	DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
paul@181 314
paul@181 315
	while ((vg_iter = readdir(vg_list)) != NULL) {
paul@181 316
		DIR		*lv_list;
paul@181 317
		char		*vdirname;
paul@181 318
		char		*vg_name;
paul@181 319
		struct dirent	*lv_iter;
paul@181 320
paul@181 321
		vg_name = vg_iter->d_name;
paul@181 322
		if (!strcmp(vg_name, ".") || !strcmp(vg_name, ".."))
paul@181 323
			continue;
paul@181 324
		vdirname = malloc(vg_len + strlen(vg_name) + 8);
paul@181 325
		if (!vdirname)
paul@181 326
			goto exit;
paul@181 327
		sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
paul@181 328
paul@181 329
		lv_list = opendir(vdirname);
paul@181 330
		free(vdirname);
paul@181 331
		if (lv_list == NULL)
paul@181 332
			continue;
paul@181 333
paul@181 334
		while ((lv_iter = readdir(lv_list)) != NULL) {
paul@181 335
			char		*lv_name, *lvm_device;
paul@181 336
paul@181 337
			lv_name = lv_iter->d_name;
paul@181 338
			if (!strcmp(lv_name, ".") || !strcmp(lv_name, ".."))
paul@181 339
				continue;
paul@181 340
paul@181 341
			lvm_device = malloc(vg_len + strlen(vg_name) +
paul@181 342
					    strlen(lv_name) + 8);
paul@181 343
			if (!lvm_device) {
paul@181 344
				closedir(lv_list);
paul@181 345
				goto exit;
paul@181 346
			}
paul@181 347
			sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
paul@181 348
				lv_name);
paul@181 349
			dev = lvm_get_devno(lvm_device);
paul@181 350
			sprintf(lvm_device, "%s/%s", vg_name, lv_name);
paul@181 351
			DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
paul@181 352
						  lvm_device,
paul@181 353
						  (unsigned int) dev));
paul@181 354
			probe_one(cache, lvm_device, dev, BLKID_PRI_LVM,
paul@181 355
				  only_if_new);
paul@181 356
			free(lvm_device);
paul@181 357
		}
paul@181 358
		closedir(lv_list);
paul@181 359
	}
paul@181 360
exit:
paul@181 361
	closedir(vg_list);
paul@181 362
}
paul@181 363
#endif
paul@181 364
paul@181 365
#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
paul@181 366
paul@181 367
static int
paul@181 368
evms_probe_all(blkid_cache cache, int only_if_new)
paul@181 369
{
paul@181 370
	char line[100];
paul@181 371
	int ma, mi, sz, num = 0;
paul@181 372
	FILE *procpt;
paul@181 373
	char device[110];
paul@181 374
paul@181 375
	procpt = fopen(PROC_EVMS_VOLUMES, "r");
paul@181 376
	if (!procpt)
paul@181 377
		return 0;
paul@181 378
	while (fgets(line, sizeof(line), procpt)) {
paul@181 379
		if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
paul@181 380
			    &ma, &mi, &sz, device) != 4)
paul@181 381
			continue;
paul@181 382
paul@181 383
		DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
paul@181 384
					  device, ma, mi));
paul@181 385
paul@181 386
		probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS,
paul@181 387
			  only_if_new);
paul@181 388
		num++;
paul@181 389
	}
paul@181 390
	fclose(procpt);
paul@181 391
	return num;
paul@181 392
}
paul@181 393
paul@181 394
/*
paul@181 395
 * Read the device data for all available block devices in the system.
paul@181 396
 */
paul@181 397
static int probe_all(blkid_cache cache, int only_if_new)
paul@181 398
{
paul@181 399
	FILE *proc;
paul@181 400
	char line[1024];
paul@181 401
	char ptname0[129], ptname1[129], *ptname = 0;
paul@181 402
	char *ptnames[2];
paul@181 403
	dev_t devs[2];
paul@181 404
	int ma, mi;
paul@181 405
	unsigned long long sz;
paul@181 406
	int lens[2] = { 0, 0 };
paul@181 407
	int which = 0, last = 0;
paul@181 408
	struct list_head *p, *pnext;
paul@181 409
paul@181 410
	ptnames[0] = ptname0;
paul@181 411
	ptnames[1] = ptname1;
paul@181 412
paul@181 413
	if (!cache)
paul@181 414
		return -BLKID_ERR_PARAM;
paul@181 415
paul@181 416
	if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
paul@181 417
	    time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
paul@181 418
		return 0;
paul@181 419
paul@181 420
	blkid_read_cache(cache);
paul@181 421
	evms_probe_all(cache, only_if_new);
paul@181 422
#ifdef VG_DIR
paul@181 423
	lvm_probe_all(cache, only_if_new);
paul@181 424
#endif
paul@181 425
paul@181 426
	proc = fopen(PROC_PARTITIONS, "r");
paul@181 427
	if (!proc)
paul@181 428
		return -BLKID_ERR_PROC;
paul@181 429
paul@181 430
	while (fgets(line, sizeof(line), proc)) {
paul@181 431
		last = which;
paul@181 432
		which ^= 1;
paul@181 433
		ptname = ptnames[which];
paul@181 434
paul@181 435
		if (sscanf(line, " %d %d %llu %128[^\n ]",
paul@181 436
			   &ma, &mi, &sz, ptname) != 4)
paul@181 437
			continue;
paul@181 438
		devs[which] = makedev(ma, mi);
paul@181 439
paul@181 440
		DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
paul@181 441
paul@181 442
		/* Skip whole disk devs unless they have no partitions.
paul@181 443
		 * If base name of device has changed, also
paul@181 444
		 * check previous dev to see if it didn't have a partn.
paul@181 445
		 * heuristic: partition name ends in a digit, & partition
paul@181 446
		 * names contain whole device name as substring.
paul@181 447
		 *
paul@181 448
		 * Skip extended partitions.
paul@181 449
		 * heuristic: size is 1
paul@181 450
		 *
paul@181 451
		 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
paul@181 452
		 */
paul@181 453
paul@181 454
		lens[which] = strlen(ptname);
paul@181 455
paul@181 456
		/* ends in a digit, clearly a partition, so check */
paul@181 457
		if (isdigit(ptname[lens[which] - 1])) {
paul@181 458
			DBG(DEBUG_DEVNAME,
paul@181 459
			    printf("partition dev %s, devno 0x%04X\n",
paul@181 460
				   ptname, (unsigned int) devs[which]));
paul@181 461
paul@181 462
			if (sz > 1)
paul@181 463
				probe_one(cache, ptname, devs[which], 0,
paul@181 464
					  only_if_new);
paul@181 465
			lens[which] = 0;	/* mark as checked */
paul@181 466
		}
paul@181 467
paul@181 468
		/*
paul@181 469
		 * If last was a whole disk and we just found a partition
paul@181 470
		 * on it, remove the whole-disk dev from the cache if
paul@181 471
		 * it exists.
paul@181 472
		 */
paul@181 473
		if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) {
paul@181 474
			list_for_each_safe(p, pnext, &cache->bic_devs) {
paul@181 475
				blkid_dev tmp;
paul@181 476
paul@181 477
				/* find blkid dev for the whole-disk devno */
paul@181 478
				tmp = list_entry(p, struct blkid_struct_dev,
paul@181 479
						 bid_devs);
paul@181 480
				if (tmp->bid_devno == devs[last]) {
paul@181 481
					DBG(DEBUG_DEVNAME,
paul@181 482
						printf("freeing %s\n",
paul@181 483
						       tmp->bid_name));
paul@181 484
					blkid_free_dev(tmp);
paul@181 485
					cache->bic_flags |= BLKID_BIC_FL_CHANGED;
paul@181 486
					break;
paul@181 487
				}
paul@181 488
			}
paul@181 489
			lens[last] = 0;
paul@181 490
		}
paul@181 491
		/*
paul@181 492
		 * If last was not checked because it looked like a whole-disk
paul@181 493
		 * dev, and the device's base name has changed,
paul@181 494
		 * check last as well.
paul@181 495
		 */
paul@181 496
		if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) {
paul@181 497
			DBG(DEBUG_DEVNAME,
paul@181 498
			    printf("whole dev %s, devno 0x%04X\n",
paul@181 499
				   ptnames[last], (unsigned int) devs[last]));
paul@181 500
			probe_one(cache, ptnames[last], devs[last], 0,
paul@181 501
				  only_if_new);
paul@181 502
			lens[last] = 0;
paul@181 503
		}
paul@181 504
	}
paul@181 505
paul@181 506
	/* Handle the last device if it wasn't partitioned */
paul@181 507
	if (lens[which])
paul@181 508
		probe_one(cache, ptname, devs[which], 0, only_if_new);
paul@181 509
paul@181 510
	fclose(proc);
paul@181 511
	blkid_flush_cache(cache);
paul@181 512
	return 0;
paul@181 513
}
paul@181 514
paul@181 515
int blkid_probe_all(blkid_cache cache)
paul@181 516
{
paul@181 517
	int ret;
paul@181 518
paul@181 519
	DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n"));
paul@181 520
	ret = probe_all(cache, 0);
paul@181 521
	cache->bic_time = time(0);
paul@181 522
	cache->bic_flags |= BLKID_BIC_FL_PROBED;
paul@181 523
	DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n"));
paul@181 524
	return ret;
paul@181 525
}
paul@181 526
paul@181 527
int blkid_probe_all_new(blkid_cache cache)
paul@181 528
{
paul@181 529
	int ret;
paul@181 530
paul@181 531
	DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n"));
paul@181 532
	ret = probe_all(cache, 1);
paul@181 533
	DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n"));
paul@181 534
	return ret;
paul@181 535
}
paul@181 536
paul@181 537
paul@181 538
#ifdef TEST_PROGRAM
paul@181 539
int main(int argc, char **argv)
paul@181 540
{
paul@181 541
	blkid_cache cache = NULL;
paul@181 542
	int ret;
paul@181 543
paul@181 544
	blkid_debug_mask = DEBUG_ALL;
paul@181 545
	if (argc != 1) {
paul@181 546
		fprintf(stderr, "Usage: %s\n"
paul@181 547
			"Probe all devices and exit\n", argv[0]);
paul@181 548
		exit(1);
paul@181 549
	}
paul@181 550
	if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
paul@181 551
		fprintf(stderr, "%s: error creating cache (%d)\n",
paul@181 552
			argv[0], ret);
paul@181 553
		exit(1);
paul@181 554
	}
paul@181 555
	if (blkid_probe_all(cache) < 0)
paul@181 556
		printf("%s: error probing devices\n", argv[0]);
paul@181 557
paul@181 558
	blkid_put_cache(cache);
paul@181 559
	return (0);
paul@181 560
}
paul@181 561
#endif