]>
git.ipfire.org Git - ipfire-2.x.git/blob - src/nash/mount_by_label.c
2 * taken from util-linux 2.11g and hacked into nash
4 * mount_by_label.c - aeb
6 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
7 * - added Native Language Support
8 * 2000-01-20 James Antill <james@and.org>
9 * - Added error message if /proc/partitions cannot be opened
10 * 2000-05-09 Erik Troan <ewt@redhat.com>
11 * - Added cache for UUID and disk labels
12 * 2000-11-07 Nathan Scott <nathans@sgi.com>
25 #include "mount_by_label.h"
27 #define PROC_PARTITIONS "/proc/partitions"
28 #define DEVLABELDIR "/dev"
32 static struct uuidCache_s
{
33 struct uuidCache_s
*next
;
40 /* for now, only ext2, ext3 and xfs are supported */
42 get_label_uuid(const char *device
, char **label
, char *uuid
) {
44 /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */
45 /* should merge these later */
49 struct ext2_super_block e2sb
;
50 struct xfs_super_block xfsb
;
52 fd
= open(device
, O_RDONLY
);
56 if (lseek(fd
, 1024, SEEK_SET
) == 1024
57 && read(fd
, (char *) &e2sb
, sizeof(e2sb
)) == sizeof(e2sb
)
58 && (ext2magic(e2sb
) == EXT2_SUPER_MAGIC
)) {
59 memcpy(uuid
, e2sb
.s_uuid
, sizeof(e2sb
.s_uuid
));
60 namesize
= sizeof(e2sb
.s_volume_name
);
61 if ((*label
= calloc(namesize
+ 1, 1)) != NULL
)
62 memcpy(*label
, e2sb
.s_volume_name
, namesize
);
65 else if (lseek(fd
, 0, SEEK_SET
) == 0
66 && read(fd
, (char *) &xfsb
, sizeof(xfsb
)) == sizeof(xfsb
)
67 && (strncmp((char *)xfsb
.s_magic
, XFS_SUPER_MAGIC
, 4) == 0)) {
68 memcpy(uuid
, xfsb
.s_uuid
, sizeof(xfsb
.s_uuid
));
69 namesize
= sizeof(xfsb
.s_fname
);
70 if ((*label
= calloc(namesize
+ 1, 1)) != NULL
)
71 memcpy(*label
, xfsb
.s_fname
, namesize
);
80 uuidcache_addentry(char * device
, int major
, int minor
, char *label
, char *uuid
) {
81 struct uuidCache_s
*last
;
84 last
= uuidCache
= malloc(sizeof(*uuidCache
));
86 for (last
= uuidCache
; last
->next
; last
= last
->next
) ;
87 last
->next
= malloc(sizeof(*uuidCache
));
92 last
->device
= device
;
95 memcpy(last
->uuid
, uuid
, sizeof(last
->uuid
));
99 uuidcache_init(void) {
103 static char ptname
[100];
105 char uuid
[16], *label
;
109 char * chptr
, * endptr
;
114 procpt
= fopen(PROC_PARTITIONS
, "r");
118 fprintf (stderr
, _("mount: could not open %s, so UUID and LABEL "
119 "conversion cannot be done.\n"),
124 for (firstPass
= 1; firstPass
>= 0; firstPass
--) {
125 fseek(procpt
, 0, SEEK_SET
);
127 while (fgets(line
, sizeof(line
), procpt
)) {
128 /* The original version of this code used sscanf, but
129 diet's sscanf is quite limited */
131 if (*chptr
++ != ' ') continue;
133 ma
= strtol(chptr
, &endptr
, 0);
134 if (endptr
== chptr
) continue;
135 while (isspace(*endptr
)) endptr
++;
138 mi
= strtol(chptr
, &endptr
, 0);
139 if (endptr
== chptr
) continue;
140 while (isspace(*endptr
)) endptr
++;
143 sz
= strtol(chptr
, &endptr
, 0);
144 if (endptr
== chptr
) continue;
145 while (isspace(*endptr
)) endptr
++;
148 while (!isspace(*endptr
) && *endptr
!= '\n') endptr
++;
149 if (chptr
== endptr
) continue;
150 strncpy(ptname
, chptr
, endptr
- chptr
);
151 ptname
[endptr
- chptr
] = '\0';
153 /* skip extended partitions (heuristic: size 1) */
157 /* look only at md devices on first pass */
158 handleOnFirst
= !strncmp(ptname
, "md", 2);
159 if (firstPass
!= handleOnFirst
)
162 /* skip entire disk (minor 0, 64, ... on ide;
164 /* heuristic: partition name ends in a digit */
166 for(s
= ptname
; *s
; s
++);
168 if (isdigit(s
[-1])) {
170 char * deviceDir
= NULL
;
172 int mustRemoveDir
= 0;
175 sprintf(device
, "%s/%s", DEVLABELDIR
, ptname
);
176 if (access(device
, F_OK
)) {
183 deviceDir
= alloca(strlen(device
) + 1);
184 strcpy(deviceDir
, device
);
185 ptr
= deviceDir
+ (strlen(device
) - 1);
188 if (mkdir(deviceDir
, 0644)) {
189 printf("mkdir: cannot create directory %s: %d\n", deviceDir
, errno
);
195 mknod(device
, S_IFBLK
| 0600, makedev(ma
, mi
));
198 if (!get_label_uuid(device
, &label
, uuid
))
199 uuidcache_addentry(strdup(device
), ma
, mi
,
202 if (mustRemove
) unlink(device
);
203 if (mustRemoveDir
) rmdir(deviceDir
);
215 get_spec_by_x(int n
, const char *t
, int * majorPtr
, int * minorPtr
) {
216 struct uuidCache_s
*uc
;
224 if (!memcmp(t
, uc
->uuid
, sizeof(uc
->uuid
))) {
225 *majorPtr
= uc
->major
;
226 *minorPtr
= uc
->minor
;
231 if (!strcmp(t
, uc
->label
)) {
232 *majorPtr
= uc
->major
;
233 *minorPtr
= uc
->minor
;
248 return (c
- 'a' + 10);
250 return (c
- 'A' + 10);
254 get_spec_by_uuid(const char *s
, int * major
, int * minor
) {
255 unsigned char uuid
[16];
258 if (strlen(s
) != 36 ||
259 s
[8] != '-' || s
[13] != '-' || s
[18] != '-' || s
[23] != '-')
261 for (i
=0; i
<16; i
++) {
263 if (!isxdigit(s
[0]) || !isxdigit(s
[1]))
265 uuid
[i
] = ((fromhex(s
[0])<<4) | fromhex(s
[1]));
268 return get_spec_by_x(UUID
, (char *)uuid
, major
, minor
);
271 fprintf(stderr
, _("mount: bad UUID"));
276 get_spec_by_volume_label(const char *s
, int * major
, int * minor
) {
277 return get_spec_by_x(VOL
, s
, major
, minor
);
280 int display_uuid_cache(void) {
281 struct uuidCache_s
* u
;
288 printf("%s %s ", u
->device
, u
->label
);
289 for (i
= 0; i
< sizeof(u
->uuid
); i
++) {
290 if (i
== 4 || i
== 6 || i
== 8 || i
== 10)
292 printf("%x", u
->uuid
[i
] & 0xff);