1 /* vi: set sw=4 ts=4: */
3 * Support functions for mounting devices by label/uuid
5 * Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
6 * Some portions cribbed from e2fsprogs, util-linux, dosfstools
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 #include <sys/mount.h> /* BLKGETSIZE64 */
11 #if !defined(BLKGETSIZE64)
12 # define BLKGETSIZE64 _IOR(0x12,114,size_t)
14 #include "volume_id_internal.h"
16 static struct uuidCache_s
{
17 struct uuidCache_s
*next
;
21 char *uc_uuid
; /* prefix makes it easier to grep for */
22 IF_FEATURE_BLKID_TYPE(const char *type
;)
25 #if !ENABLE_FEATURE_BLKID_TYPE
26 #define get_label_uuid(fd, label, uuid, type) \
27 get_label_uuid(fd, label, uuid)
28 #define uuidcache_addentry(device, devno, label, uuid, type) \
29 uuidcache_addentry(device, devno, label, uuid)
32 /* Returns !0 on error.
33 * Otherwise, returns malloc'ed strings for label and uuid
34 * (and they can't be NULL, although they can be "").
37 get_label_uuid(int fd
, char **label
, char **uuid
, const char **type
)
41 struct volume_id
*vid
;
43 /* fd is owned by vid now */
44 vid
= volume_id_open_node(fd
);
46 if (ioctl(/*vid->*/fd
, BLKGETSIZE64
, &size
) != 0)
49 if (volume_id_probe_all(vid
, /*0,*/ size
) != 0)
52 if (vid
->label
[0] != '\0' || vid
->uuid
[0] != '\0'
53 #if ENABLE_FEATURE_BLKID_TYPE
57 *label
= xstrndup(vid
->label
, sizeof(vid
->label
));
58 *uuid
= xstrndup(vid
->uuid
, sizeof(vid
->uuid
));
59 #if ENABLE_FEATURE_BLKID_TYPE
61 dbg("found label '%s', uuid '%s', type '%s'", *label
, *uuid
, *type
);
63 dbg("found label '%s', uuid '%s'", *label
, *uuid
);
68 free_volume_id(vid
); /* also closes fd */
72 /* NB: we take ownership of (malloc'ed) label and uuid */
74 uuidcache_addentry(char *device
, dev_t devno
, char *label
, char *uuid
, const char *type
)
76 struct uuidCache_s
*last
;
79 last
= uuidCache
= xzalloc(sizeof(*uuidCache
));
81 for (last
= uuidCache
; last
->next
; last
= last
->next
)
83 last
->next
= xzalloc(sizeof(*uuidCache
));
86 /*last->next = NULL; - xzalloc did it*/
88 last
->device
= device
;
91 IF_FEATURE_BLKID_TYPE(last
->type
= type
;)
94 /* If get_label_uuid() on device_name returns success,
95 * add a cache entry for this device.
96 * If device node does not exist, it will be temporarily created. */
98 uuidcache_check_device(const char *device
,
100 void *userData UNUSED_PARAM
,
101 int depth UNUSED_PARAM
)
103 /* note: this check rejects links to devices, among other nodes */
104 if (!S_ISBLK(statbuf
->st_mode
))
107 /* Users report that mucking with floppies (especially non-present
108 * ones) is significant PITA. This is a horribly dirty hack,
109 * but it is very useful in real world.
110 * If this will ever need to be enabled, consider using O_NONBLOCK.
112 if (major(statbuf
->st_rdev
) == 2)
115 add_to_uuid_cache(device
, statbuf
->st_rdev
);
120 static struct uuidCache_s
*
121 uuidcache_init(int scan_devices
)
123 dbg("DBG: uuidCache=%x, uuidCache");
127 /* We were scanning /proc/partitions
128 * and /proc/sys/dev/cdrom/info here.
129 * Missed volume managers. I see that "standard" blkid uses these:
130 * /dev/mapper/control
134 * This is unacceptably complex. Let's just scan /dev.
135 * (Maybe add scanning of /sys/block/XXX/dev for devices
136 * somehow not having their /dev/XXX entries created?) */
138 recursive_action("/dev", ACTION_RECURSE
,
139 uuidcache_check_device
, /* file_action */
140 NULL
, /* dir_action */
152 get_spec_by_x(int n
, const char *t
, dev_t
*devnoPtr
)
154 struct uuidCache_s
*uc
;
156 uc
= uuidcache_init(/*scan_devices:*/ 1);
160 /* case of hex numbers doesn't matter */
161 if (strcasecmp(t
, uc
->uc_uuid
) == 0)
165 if (uc
->label
[0] && strcmp(t
, uc
->label
) == 0)
169 if (uc
->devno
== (*devnoPtr
))
179 *devnoPtr
= uc
->devno
;
180 return xstrdup(uc
->device
);
184 void display_uuid_cache(int scan_devices
)
186 struct uuidCache_s
*uc
;
188 uc
= uuidcache_init(scan_devices
);
190 printf("%s:", uc
->device
);
192 printf(" LABEL=\"%s\"", uc
->label
);
194 printf(" UUID=\"%s\"", uc
->uc_uuid
);
195 #if ENABLE_FEATURE_BLKID_TYPE
197 printf(" TYPE=\"%s\"", uc
->type
);
204 int add_to_uuid_cache(const char *device
, dev_t devno
)
206 char *uuid
= uuid
; /* for compiler */
208 #if ENABLE_FEATURE_BLKID_TYPE
209 const char *type
= type
;
213 fd
= open(device
, O_RDONLY
);
217 /* get_label_uuid() closes fd in all cases (success & failure) */
218 if (get_label_uuid(fd
, &label
, &uuid
, &type
) == 0) {
219 /* uuidcache_addentry() takes ownership of all four params */
220 uuidcache_addentry(xstrdup(device
), devno
, label
, uuid
, type
);
227 /* Used by mount and findfs & old_e2fsprogs */
229 char *get_devname_from_label(const char *spec
)
231 return get_spec_by_x(VOL
, spec
, NULL
);
234 char *get_devname_from_uuid(const char *spec
)
236 return get_spec_by_x(UUID
, spec
, NULL
);
239 char *get_devname_from_device(dev_t dev
)
241 return get_spec_by_x(DEVNO
, NULL
, &dev
);
244 int resolve_mount_spec(char **fsname
)
248 if (strncmp(*fsname
, "UUID=", 5) == 0)
249 tmp
= get_devname_from_uuid(*fsname
+ 5);
250 else if (strncmp(*fsname
, "LABEL=", 6) == 0)
251 tmp
= get_devname_from_label(*fsname
+ 6);
253 *fsname
= xstrdup(*fsname
);
254 return 0; /* no UUID= or LABEL= prefix found */
258 return -2; /* device defined by UUID= or LABEL= wasn't found */