]>
git.wh0rd.org - dump.git/blob - compat/lib/bylabel.c
2 * mount_by_label.c - aeb
4 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
5 * - added Native Language Support
6 * 2000-01-20 James Antill <james@and.org>
7 * - Added error message if /proc/partitions cannot be opened
8 * 2000-05-09 Erik Troan <ewt@redhat.com>
9 * - Added cache for UUID and disk labels
10 * Wed Aug 16 2000 Erik Troan <ewt@redhat.com>
11 * - Ported to dump/restore
15 #include <compatlfs.h>
17 #include <sys/param.h>
25 #define PROC_PARTITIONS "/proc/partitions"
26 #define DEVLABELDIR "/dev"
28 #define EXT2_SUPER_OFFSET 1024
29 #define EXT2_SUPER_SIZE sizeof(struct ext2_super_block)
30 #define EXT2_SUPER_MAGIC 0xEF53
34 struct ext2_super_block
{
35 unsigned char s_dummy1
[56];
36 unsigned char s_magic
[2];
37 unsigned char s_dummy2
[46];
38 unsigned char s_uuid
[16];
39 unsigned char s_volume_name
[VOLNAMSZ
];
41 #define ext2magic(s) ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
43 void msg
__P((const char *fmt
, ...));
45 static struct uuidCache_s
{
46 struct uuidCache_s
*next
;
52 /* for now, only ext2 is supported */
54 get_label_uuid(const char *device
, char **label
, char *uuid
) {
56 /* start with a test for ext2, taken from mount_guess_fstype */
57 /* should merge these later */
59 struct ext2_super_block e2sb
;
61 fd
= OPEN(device
, O_RDONLY
);
65 if (LSEEK(fd
, EXT2_SUPER_OFFSET
, SEEK_SET
) != EXT2_SUPER_OFFSET
||
66 read(fd
, (char *) &e2sb
, EXT2_SUPER_SIZE
) != EXT2_SUPER_SIZE
||
67 ext2magic(e2sb
) != EXT2_SUPER_MAGIC
) {
74 /* superblock is ext2 - now what is its label? */
75 memcpy(uuid
, e2sb
.s_uuid
, sizeof(e2sb
.s_uuid
));
76 *label
= malloc(VOLNAMSZ
+ 1);
77 strncpy(*label
, e2sb
.s_volume_name
, VOLNAMSZ
);
78 (*label
)[VOLNAMSZ
] = 0;
84 uuidcache_addentry(char *device
, char *label
, char *uuid
) {
85 struct uuidCache_s
*last
;
88 last
= uuidCache
= (struct uuidCache_s
*)malloc(sizeof(*uuidCache
));
90 for (last
= uuidCache
; last
->next
; last
= last
->next
) ;
91 last
->next
= (struct uuidCache_s
*)malloc(sizeof(*uuidCache
));
95 last
->device
= device
;
97 memcpy(last
->uuid
, uuid
, sizeof(last
->uuid
));
101 uuidcache_init(void) {
105 static char ptname
[100];
107 char uuid
[16], *label
;
115 procpt
= fopen(PROC_PARTITIONS
, "r");
119 for (firstPass
= 1; firstPass
>= 0; firstPass
--) {
120 fseek(procpt
, 0, SEEK_SET
);
122 while (fgets(line
, sizeof(line
), procpt
)) {
123 if (sscanf (line
, " %d %d %d %[^\n ]",
124 &ma
, &mi
, &sz
, ptname
) != 4)
127 /* skip extended partitions (heuristic: size 1) */
131 /* look only at md devices on first pass */
132 handleOnFirst
= !strncmp(ptname
, "md", 2);
133 if (firstPass
!= handleOnFirst
)
136 /* skip entire disk (minor 0, 64, ... on ide;
138 /* heuristic: partition name ends in a digit */
140 for(s
= ptname
; *s
; s
++);
141 if (isdigit(s
[-1])) {
143 * Note: this is a heuristic only - there is no reason
144 * why these devices should live in /dev.
145 * Perhaps this directory should be specifiable by option.
146 * One might for example have /devlabel with links to /dev
147 * for the devices that may be accessed in this way.
148 * (This is useful, if the cdrom on /dev/hdc must not
151 sprintf(device
, "%s/%s", DEVLABELDIR
, ptname
);
152 if (!get_label_uuid(device
, &label
, uuid
))
153 uuidcache_addentry(strdup(device
), label
, uuid
);
165 get_spec_by_x(int n
, const char *t
) {
166 struct uuidCache_s
*uc
;
174 if (!memcmp(t
, uc
->uuid
, sizeof(uc
->uuid
)))
175 return strdup(uc
->device
);
178 if (!strcmp(t
, uc
->label
))
179 return strdup(uc
->device
);
192 return (c
- 'a' + 10);
194 return (c
- 'A' + 10);
198 get_spec_by_uuid(const char *s
) {
202 if (strlen(s
) != 36 ||
203 s
[8] != '-' || s
[13] != '-' || s
[18] != '-' || s
[23] != '-')
205 for (i
=0; i
<16; i
++) {
207 if (!isxdigit(s
[0]) || !isxdigit(s
[1]))
209 uuid
[i
] = ((fromhex(s
[0])<<4) | fromhex(s
[1]));
212 return get_spec_by_x(UUID
, uuid
);
215 msg("mount: bad UUID\n");
216 return NULL
; /* just for gcc */
220 get_spec_by_volume_label(const char *s
) {
221 return get_spec_by_x(VOL
, s
);
225 get_device_name(const char * item
) {
228 if (!strncmp(item
, "UUID=", 5)) {
229 rc
= get_spec_by_uuid(item
+5);
232 if (!strncmp(item
, "LABEL=", 6)) {
233 rc
= get_spec_by_volume_label(item
+6);
243 get_device_label(const char * spec
) {
244 struct uuidCache_s
*uc
;
250 if (!strcmp(spec
, uc
->device
))
251 return uc
->label
[0] == '\0' ? NULL
: strdup(uc
->label
);