volume identification: abolish /proc/partitions and /proc/cdroms

scanning. It does not catch volume managers and such.
Adding even more cruft is bad, so I decided to simply
scan /dev/* for any block devices. See how much better
it finds devices now:

# ./busybox_old blkid
/dev/sda1: LABEL="/boot" UUID="7931e231-dcb4-4b6d-9301-f7354ae24061"
/dev/dm-0: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/dm-1: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/sdb1: UUID="6F84-ED0F"

# ./busybox blkid
/dev/sdb1: UUID="6F84-ED0F"
/dev/root: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/dm-1: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/dm-0: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"
/dev/sda1: LABEL="/boot" UUID="7931e231-dcb4-4b6d-9301-f7354ae24061"
/dev/mapper/VolGroup00-LogVol01: UUID="edc2a920-ef83-437e-ba64-d3b6dc851267"
/dev/mapper/VolGroup00-LogVol00: LABEL="Fedora-9-Live-x8" UUID="bb491e1e-1145-4f5b-b0ab-cbd2baf4f15a"

function                                             old     new   delta
static.drive_name_string                              12       -     -12
append_mount_options                                 205     190     -15
volume_id_open_node                                   37      18     -19
uuidcache_check_device                               485     257    -228
uuidcache_init                                       637      36    -601
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 0/4 up/down: 0/-875)           Total: -875 bytes
   text    data     bss     dec     hex filename
 792218     592    6648  799458   c32e2 busybox_old
 791260     592    6648  798500   c2f24 busybox_unstripped
This commit is contained in:
Denis Vlasenko 2008-10-19 19:36:30 +00:00
parent bff06fe02a
commit 582dff0514
5 changed files with 35 additions and 227 deletions

View File

@ -1189,7 +1189,7 @@ static char **get_recursive_dirlist(char *path)
recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS, recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS,
add_to_dirlist, /* file_action */ add_to_dirlist, /* file_action */
NULL, /* dir_action */ NULL, /* dir_action */
(void*)(strlen(path) + 1), (void*)(ptrdiff_t)(strlen(path) + 1),
0); 0);
} else { } else {
DIR *dp; DIR *dp;

View File

@ -71,7 +71,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
} }
/* Since the directory exists, don't attempt to change /* Since the directory exists, don't attempt to change
* permissions if it was the full target. Note that * permissions if it was the full target. Note that
* this is not an error conditon. */ * this is not an error condition. */
if (!c) { if (!c) {
umask(mask); umask(mask);
return 0; return 0;

View File

@ -22,38 +22,23 @@ static struct uuidCache_s {
/* Returns !0 on error. /* Returns !0 on error.
* Otherwise, returns malloc'ed strings for label and uuid * Otherwise, returns malloc'ed strings for label and uuid
* (and they can't be NULL, although they can be "") */ * (and they can't be NULL, although they can be "").
#if !ENABLE_FEATURE_VOLUMEID_ISO9660 * NB: closes fd. */
#define get_label_uuid(device, label, uuid, iso_only) \
get_label_uuid(device, label, uuid)
#endif
static int static int
get_label_uuid(const char *device, char **label, char **uuid, int iso_only) get_label_uuid(int fd, char **label, char **uuid)
{ {
int rv = 1; int rv = 1;
uint64_t size; uint64_t size;
struct volume_id *vid; struct volume_id *vid;
vid = volume_id_open_node(device); /* fd is owned by vid now */
if (!vid) vid = volume_id_open_node(fd);
return rv;
if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) if (ioctl(/*vid->*/fd, BLKGETSIZE64, &size) != 0)
size = 0; size = 0;
#if ENABLE_FEATURE_VOLUMEID_ISO9660 if (volume_id_probe_all(vid, 0, size) != 0)
if ((iso_only ?
volume_id_probe_iso9660(vid, 0) :
volume_id_probe_all(vid, 0, size)
) != 0
) {
goto ret; goto ret;
}
#else
if (volume_id_probe_all(vid, 0, size) != 0) {
goto ret;
}
#endif
if (vid->label[0] != '\0' || vid->uuid[0] != '\0') { if (vid->label[0] != '\0' || vid->uuid[0] != '\0') {
*label = xstrndup(vid->label, sizeof(vid->label)); *label = xstrndup(vid->label, sizeof(vid->label));
@ -62,7 +47,7 @@ get_label_uuid(const char *device, char **label, char **uuid, int iso_only)
rv = 0; rv = 0;
} }
ret: ret:
free_volume_id(vid); free_volume_id(vid); /* also closes fd */
return rv; return rv;
} }
@ -91,204 +76,29 @@ uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uu
/* If get_label_uuid() on device_name returns success, /* If get_label_uuid() on device_name returns success,
* add a cache entry for this device. * add a cache entry for this device.
* If device node does not exist, it will be temporarily created. */ * If device node does not exist, it will be temporarily created. */
#if !ENABLE_FEATURE_VOLUMEID_ISO9660 static int FAST_FUNC
#define uuidcache_check_device(device_name, ma, mi, iso_only) \ uuidcache_check_device(const char *device,
uuidcache_check_device(device_name, ma, mi) struct stat *statbuf,
#endif void *userData UNUSED_PARAM,
static void int depth UNUSED_PARAM)
uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only)
{ {
char *device, *last_slash; char *uuid = uuid; /* for compiler */
char *uuid, *label; char *label = label;
char *ptr; int fd;
int must_remove = 0;
int added = 0;
last_slash = NULL; if (!S_ISBLK(statbuf->st_mode))
device = xasprintf("/dev/%s", device_name); return TRUE;
if (access(device, F_OK) != 0) {
/* device does not exist, temporarily create */
int slash_cnt = 0;
if ((ma | mi) < 0) fd = open(device, O_RDONLY);
goto ret; /* we don't know major:minor! */ if (fd < 0)
return TRUE;
ptr = device; /* get_label_uuid() closes fd in all cases (success & failure) */
while (*ptr) if (get_label_uuid(fd, &label, &uuid) == 0) {
if (*ptr++ == '/') /* uuidcache_addentry() takes ownership of all three params */
slash_cnt++; uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid);
if (slash_cnt > 2) {
// BUG: handles only slash_cnt == 3 case
last_slash = strrchr(device, '/');
*last_slash = '\0';
if (mkdir(device, 0644)) {
bb_perror_msg("can't create directory %s", device);
*last_slash = '/';
last_slash = NULL; /* prevents rmdir */
} else {
*last_slash = '/';
} }
} return TRUE;
mknod(device, S_IFBLK | 0600, makedev(ma, mi));
must_remove = 1;
}
uuid = NULL;
label = NULL;
if (get_label_uuid(device, &label, &uuid, iso_only) == 0) {
uuidcache_addentry(device, /*ma, mi,*/ label, uuid);
/* "device" is owned by cache now, don't free */
added = 1;
}
if (must_remove)
unlink(device);
if (last_slash) {
*last_slash = '\0';
rmdir(device);
}
ret:
if (!added)
free(device);
}
/* Run uuidcache_check_device() for every device mentioned
* in /proc/partitions */
static void
uuidcache_init_partitions(void)
{
char line[100];
int ma, mi;
unsigned long long sz;
FILE *procpt;
int firstPass;
int handleOnFirst;
char *chptr;
procpt = xfopen_for_read("/proc/partitions");
/*
# cat /proc/partitions
major minor #blocks name
8 0 293036184 sda
8 1 6835626 sda1
8 2 1 sda2
8 5 979933 sda5
8 6 15623181 sda6
8 7 97659103 sda7
8 8 171935631 sda8
*/
for (firstPass = 1; firstPass >= 0; firstPass--) {
fseek(procpt, 0, SEEK_SET);
while (fgets(line, sizeof(line), procpt)) {
/* The original version of this code used sscanf, but
diet's sscanf is quite limited */
chptr = line;
if (*chptr != ' ') continue;
chptr = skip_whitespace(chptr);
ma = bb_strtou(chptr, &chptr, 0);
if (ma < 0) continue;
chptr = skip_whitespace(chptr);
mi = bb_strtou(chptr, &chptr, 0);
if (mi < 0) continue;
chptr = skip_whitespace(chptr);
sz = bb_strtoull(chptr, &chptr, 0);
if ((long long)sz == -1LL) continue;
chptr = skip_whitespace(chptr);
/* skip extended partitions (heuristic: size 1) */
if (sz == 1)
continue;
*strchrnul(chptr, '\n') = '\0';
/* now chptr => device name */
dbg("/proc/partitions: maj:%d min:%d sz:%llu name:'%s'",
ma, mi, sz, chptr);
if (!chptr[0])
continue;
/* look only at md devices on first pass */
handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd');
if (firstPass != handleOnFirst)
continue;
/* heuristic: partition name ends in a digit */
if (isdigit(chptr[strlen(chptr) - 1])) {
uuidcache_check_device(chptr, ma, mi, 0);
}
}
}
fclose(procpt);
}
static void
dev_get_major_minor(char *device_name, int *major, int *minor)
{
char dev[16];
char *dev_path;
char *colon;
int sz;
dev_path = xasprintf("/sys/block/%s/dev", device_name);
sz = open_read_close(dev_path, dev, sizeof(dev) - 1);
if (sz < 0)
goto ret;
dev[sz] = '\0';
colon = strchr(dev, ':');
if (!colon)
goto ret;
*major = bb_strtou(dev, NULL, 10);
*minor = bb_strtou(colon + 1, NULL, 10);
ret:
free(dev_path);
return;
}
static void
uuidcache_init_cdroms(void)
{
#define PROC_CDROMS "/proc/sys/dev/cdrom/info"
char line[100];
int ma, mi;
FILE *proccd;
proccd = fopen_for_read(PROC_CDROMS);
if (!proccd) {
// static smallint warn = 0;
// if (!warn) {
// warn = 1;
// bb_error_msg("can't open %s, UUID and LABEL "
// "conversion cannot be done for CD-Roms",
// PROC_CDROMS);
// }
return;
}
while (fgets(line, sizeof(line), proccd)) {
static const char drive_name_string[] ALIGN1 = "drive name:";
if (strncmp(line, drive_name_string, sizeof(drive_name_string) - 1) == 0) {
char *device_name;
device_name = strtok(skip_whitespace(line + sizeof(drive_name_string) - 1), " \t\n");
while (device_name && device_name[0]) {
ma = mi = -1;
dev_get_major_minor(device_name, &ma, &mi);
uuidcache_check_device(device_name, ma, mi, 1);
device_name = strtok(NULL, " \t\n");
}
break;
}
}
fclose(proccd);
} }
static void static void
@ -297,8 +107,11 @@ uuidcache_init(void)
if (uuidCache) if (uuidCache)
return; return;
uuidcache_init_partitions(); recursive_action("/dev", ACTION_RECURSE,
uuidcache_init_cdroms(); uuidcache_check_device, /* file_action */
NULL, /* dir_action */
NULL, /* userData */
0 /* depth */);
} }
#define UUID 1 #define UUID 1

View File

@ -190,19 +190,14 @@ int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
} }
/* open volume by device node */ /* open volume by device node */
struct volume_id *volume_id_open_node(const char *path) struct volume_id *volume_id_open_node(int fd)
{ {
struct volume_id *id; struct volume_id *id;
int fd;
fd = open(path, O_RDONLY);
if (fd < 0)
return NULL;
id = xzalloc(sizeof(struct volume_id)); id = xzalloc(sizeof(struct volume_id));
id->fd = fd; id->fd = fd;
///* close fd on device close */ ///* close fd on device close */
//id->fd_close = 1; //id->fd_close = 1;
return id; return id;
} }

View File

@ -87,7 +87,7 @@ struct volume_id {
// int fd_close:1; // int fd_close:1;
}; };
struct volume_id *volume_id_open_node(const char *path); struct volume_id *volume_id_open_node(int fd);
int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
void free_volume_id(struct volume_id *id); void free_volume_id(struct volume_id *id);