source: MondoRescue/branches/3.3/mindi-busybox/util-linux/volume_id/get_devname.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Support functions for mounting devices by label/uuid
4 *
5 * Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
6 * Some portions cribbed from e2fsprogs, util-linux, dosfstools
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10
11//kbuild:lib-$(CONFIG_BLKID) += get_devname.o
12//kbuild:lib-$(CONFIG_FINDFS) += get_devname.o
13//kbuild:lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
14
15#include <sys/mount.h> /* BLKGETSIZE64 */
16#if !defined(BLKGETSIZE64)
17# define BLKGETSIZE64 _IOR(0x12,114,size_t)
18#endif
19#include "volume_id_internal.h"
20
21static struct uuidCache_s {
22 struct uuidCache_s *next;
23// int major, minor;
24 char *device;
25 char *label;
26 char *uc_uuid; /* prefix makes it easier to grep for */
27 IF_FEATURE_BLKID_TYPE(const char *type;)
28} *uuidCache;
29
30#if !ENABLE_FEATURE_BLKID_TYPE
31#define get_label_uuid(fd, label, uuid, type) \
32 get_label_uuid(fd, label, uuid)
33#define uuidcache_addentry(device, label, uuid, type) \
34 uuidcache_addentry(device, label, uuid)
35#endif
36
37/* Returns !0 on error.
38 * Otherwise, returns malloc'ed strings for label and uuid
39 * (and they can't be NULL, although they can be "").
40 * NB: closes fd. */
41static int
42get_label_uuid(int fd, char **label, char **uuid, const char **type)
43{
44 int rv = 1;
45 uint64_t size;
46 struct volume_id *vid;
47
48 /* fd is owned by vid now */
49 vid = volume_id_open_node(fd);
50
51 if (ioctl(/*vid->*/fd, BLKGETSIZE64, &size) != 0)
52 size = 0;
53
54 if (volume_id_probe_all(vid, /*0,*/ size) != 0)
55 goto ret;
56
57 if (vid->label[0] != '\0' || vid->uuid[0] != '\0'
58#if ENABLE_FEATURE_BLKID_TYPE
59 || vid->type != NULL
60#endif
61 ) {
62 *label = xstrndup(vid->label, sizeof(vid->label));
63 *uuid = xstrndup(vid->uuid, sizeof(vid->uuid));
64#if ENABLE_FEATURE_BLKID_TYPE
65 *type = vid->type;
66 dbg("found label '%s', uuid '%s', type '%s'", *label, *uuid, *type);
67#else
68 dbg("found label '%s', uuid '%s'", *label, *uuid);
69#endif
70 rv = 0;
71 }
72 ret:
73 free_volume_id(vid); /* also closes fd */
74 return rv;
75}
76
77/* NB: we take ownership of (malloc'ed) label and uuid */
78static void
79uuidcache_addentry(char *device, /*int major, int minor,*/ char *label, char *uuid, const char *type)
80{
81 struct uuidCache_s *last;
82
83 if (!uuidCache) {
84 last = uuidCache = xzalloc(sizeof(*uuidCache));
85 } else {
86 for (last = uuidCache; last->next; last = last->next)
87 continue;
88 last->next = xzalloc(sizeof(*uuidCache));
89 last = last->next;
90 }
91 /*last->next = NULL; - xzalloc did it*/
92// last->major = major;
93// last->minor = minor;
94 last->device = device;
95 last->label = label;
96 last->uc_uuid = uuid;
97 IF_FEATURE_BLKID_TYPE(last->type = type;)
98}
99
100/* If get_label_uuid() on device_name returns success,
101 * add a cache entry for this device.
102 * If device node does not exist, it will be temporarily created. */
103static int FAST_FUNC
104uuidcache_check_device(const char *device,
105 struct stat *statbuf,
106 void *userData UNUSED_PARAM,
107 int depth UNUSED_PARAM)
108{
109 /* note: this check rejects links to devices, among other nodes */
110 if (!S_ISBLK(statbuf->st_mode))
111 return TRUE;
112
113 /* Users report that mucking with floppies (especially non-present
114 * ones) is significant PITA. This is a horribly dirty hack,
115 * but it is very useful in real world.
116 * If this will ever need to be enabled, consider using O_NONBLOCK.
117 */
118 if (major(statbuf->st_rdev) == 2)
119 return TRUE;
120
121 add_to_uuid_cache(device);
122
123 return TRUE;
124}
125
126static struct uuidCache_s*
127uuidcache_init(int scan_devices)
128{
129 dbg("DBG: uuidCache=%x, uuidCache");
130 if (uuidCache)
131 return uuidCache;
132
133 /* We were scanning /proc/partitions
134 * and /proc/sys/dev/cdrom/info here.
135 * Missed volume managers. I see that "standard" blkid uses these:
136 * /dev/mapper/control
137 * /proc/devices
138 * /proc/evms/volumes
139 * /proc/lvm/VGs
140 * This is unacceptably complex. Let's just scan /dev.
141 * (Maybe add scanning of /sys/block/XXX/dev for devices
142 * somehow not having their /dev/XXX entries created?) */
143 if (scan_devices)
144 recursive_action("/dev", ACTION_RECURSE,
145 uuidcache_check_device, /* file_action */
146 NULL, /* dir_action */
147 NULL, /* userData */
148 0 /* depth */);
149
150 return uuidCache;
151}
152
153#define UUID 1
154#define VOL 2
155
156#ifdef UNUSED
157static char *
158get_spec_by_x(int n, const char *t, int *majorPtr, int *minorPtr)
159{
160 struct uuidCache_s *uc;
161
162 uc = uuidcache_init(/*scan_devices:*/ 1);
163 while (uc) {
164 switch (n) {
165 case UUID:
166 if (strcmp(t, uc->uc_uuid) == 0) {
167 *majorPtr = uc->major;
168 *minorPtr = uc->minor;
169 return uc->device;
170 }
171 break;
172 case VOL:
173 if (strcmp(t, uc->label) == 0) {
174 *majorPtr = uc->major;
175 *minorPtr = uc->minor;
176 return uc->device;
177 }
178 break;
179 }
180 uc = uc->next;
181 }
182 return NULL;
183}
184
185static unsigned char
186fromhex(char c)
187{
188 if (isdigit(c))
189 return (c - '0');
190 return ((c|0x20) - 'a' + 10);
191}
192
193static char *
194get_spec_by_uuid(const char *s, int *major, int *minor)
195{
196 unsigned char uuid[16];
197 int i;
198
199 if (strlen(s) != 36 || s[8] != '-' || s[13] != '-'
200 || s[18] != '-' || s[23] != '-'
201 ) {
202 goto bad_uuid;
203 }
204 for (i = 0; i < 16; i++) {
205 if (*s == '-')
206 s++;
207 if (!isxdigit(s[0]) || !isxdigit(s[1]))
208 goto bad_uuid;
209 uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
210 s += 2;
211 }
212 return get_spec_by_x(UUID, (char *)uuid, major, minor);
213
214 bad_uuid:
215 fprintf(stderr, _("mount: bad UUID"));
216 return 0;
217}
218
219static char *
220get_spec_by_volume_label(const char *s, int *major, int *minor)
221{
222 return get_spec_by_x(VOL, s, major, minor);
223}
224#endif // UNUSED
225
226/* Used by blkid */
227void display_uuid_cache(int scan_devices)
228{
229 struct uuidCache_s *uc;
230
231 uc = uuidcache_init(scan_devices);
232 while (uc) {
233 printf("%s:", uc->device);
234 if (uc->label[0])
235 printf(" LABEL=\"%s\"", uc->label);
236 if (uc->uc_uuid[0])
237 printf(" UUID=\"%s\"", uc->uc_uuid);
238#if ENABLE_FEATURE_BLKID_TYPE
239 if (uc->type)
240 printf(" TYPE=\"%s\"", uc->type);
241#endif
242 bb_putchar('\n');
243 uc = uc->next;
244 }
245}
246
247int add_to_uuid_cache(const char *device)
248{
249 char *uuid = uuid; /* for compiler */
250 char *label = label;
251#if ENABLE_FEATURE_BLKID_TYPE
252 const char *type = type;
253#endif
254 int fd;
255
256 fd = open(device, O_RDONLY);
257 if (fd < 0)
258 return 0;
259
260 /* get_label_uuid() closes fd in all cases (success & failure) */
261 if (get_label_uuid(fd, &label, &uuid, &type) == 0) {
262 /* uuidcache_addentry() takes ownership of all four params */
263 uuidcache_addentry(xstrdup(device), /*ma, mi,*/ label, uuid, type);
264 return 1;
265 }
266 return 0;
267}
268
269
270/* Used by mount and findfs */
271
272char *get_devname_from_label(const char *spec)
273{
274 struct uuidCache_s *uc;
275
276 uc = uuidcache_init(/*scan_devices:*/ 1);
277 while (uc) {
278 if (uc->label[0] && strcmp(spec, uc->label) == 0) {
279 return xstrdup(uc->device);
280 }
281 uc = uc->next;
282 }
283 return NULL;
284}
285
286char *get_devname_from_uuid(const char *spec)
287{
288 struct uuidCache_s *uc;
289
290 uc = uuidcache_init(/*scan_devices:*/ 1);
291 while (uc) {
292 /* case of hex numbers doesn't matter */
293 if (strcasecmp(spec, uc->uc_uuid) == 0) {
294 return xstrdup(uc->device);
295 }
296 uc = uc->next;
297 }
298 return NULL;
299}
300
301int resolve_mount_spec(char **fsname)
302{
303 char *tmp = *fsname;
304
305 if (is_prefixed_with(*fsname, "UUID="))
306 tmp = get_devname_from_uuid(*fsname + 5);
307 else if (is_prefixed_with(*fsname, "LABEL="))
308 tmp = get_devname_from_label(*fsname + 6);
309
310 if (tmp == *fsname)
311 return 0; /* no UUID= or LABEL= prefix found */
312
313 if (tmp)
314 *fsname = tmp;
315 return 1;
316}
Note: See TracBrowser for help on using the repository browser.