Magellan Linux

Annotation of /tags/mkinitrd-6_2_0/nash/mount_by_label.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
Original Path: trunk/mkinitrd-magellan/nash/mount_by_label.c
File MIME type: text/plain
File size: 6885 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /*
2     * taken from util-linux 2.11g and hacked into nash
3     *
4     * mount_by_label.c - aeb
5     *
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>
13     * - Added XFS support
14     */
15    
16     #include <errno.h>
17     #include <stdio.h>
18     #include <string.h>
19     #include <ctype.h>
20     #include <fcntl.h>
21     #include <stdlib.h>
22     #include <unistd.h>
23     #include <sys/stat.h>
24     #include "linux_fs.h"
25     #include "mount_by_label.h"
26    
27     #define PROC_PARTITIONS "/proc/partitions"
28     #define DEVLABELDIR "/dev"
29    
30     #define _(str) (str)
31    
32     static struct uuidCache_s {
33     struct uuidCache_s *next;
34     char uuid[16];
35     char *device;
36     char *label;
37     int major, minor;
38     } *uuidCache = NULL;
39    
40     /* for now, only ext2, ext3 and xfs are supported */
41     static int
42     get_label_uuid(const char *device, char **label, char *uuid) {
43    
44     /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */
45     /* should merge these later */
46     int fd;
47     int rv = 1;
48     size_t namesize;
49     struct ext2_super_block e2sb;
50     struct xfs_super_block xfsb;
51    
52     fd = open(device, O_RDONLY);
53     if (fd < 0)
54     return rv;
55    
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);
63     rv = 0;
64     }
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);
72     rv = 0;
73     }
74    
75     close(fd);
76     return rv;
77     }
78    
79     static void
80     uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) {
81     struct uuidCache_s *last;
82    
83     if (!uuidCache) {
84     last = uuidCache = calloc(1, sizeof (*uuidCache));
85     } else {
86     for (last = uuidCache; last->next; last = last->next) ;
87     last->next = calloc(1, sizeof (*uuidCache));
88     last = last->next;
89     }
90     last->next = NULL;
91     last->label = label;
92     last->device = device;
93     last->major = major;
94     last->minor = minor;
95     memcpy(last->uuid, uuid, sizeof(last->uuid));
96     }
97    
98     static void
99     uuidcache_init(void) {
100     char line[100];
101     char *s;
102     int ma, mi, sz;
103     static char ptname[100];
104     FILE *procpt;
105     char uuid[16], *label;
106     char device[110];
107     int firstPass;
108     int handleOnFirst;
109     char * chptr, * endptr;
110    
111     if (uuidCache)
112     return;
113    
114     procpt = fopen(PROC_PARTITIONS, "r");
115     if (!procpt) {
116     static int warn = 0;
117     if (!warn++)
118     fprintf (stderr, _("mount: could not open %s, so UUID and LABEL "
119     "conversion cannot be done.\n"),
120     PROC_PARTITIONS);
121     return;
122     }
123    
124     for (firstPass = 1; firstPass >= 0; firstPass--) {
125     fseek(procpt, 0, SEEK_SET);
126    
127     while (fgets(line, sizeof(line), procpt)) {
128     /* The original version of this code used sscanf, but
129     diet's sscanf is quite limited */
130     chptr = line;
131     if (*chptr++ != ' ') continue;
132    
133     ma = strtol(chptr, &endptr, 0);
134     if (endptr == chptr) continue;
135     while (isspace(*endptr)) endptr++;
136     chptr = endptr;
137    
138     mi = strtol(chptr, &endptr, 0);
139     if (endptr == chptr) continue;
140     while (isspace(*endptr)) endptr++;
141     chptr = endptr;
142    
143     sz = strtol(chptr, &endptr, 0);
144     if (endptr == chptr) continue;
145     while (isspace(*endptr)) endptr++;
146     chptr = endptr;
147    
148     while (!isspace(*endptr) && *endptr != '\n') endptr++;
149     if (chptr == endptr) continue;
150     strncpy(ptname, chptr, endptr - chptr);
151     ptname[endptr - chptr] = '\0';
152    
153     /* skip extended partitions (heuristic: size 1) */
154     if (sz == 1)
155     continue;
156    
157     /* look only at md devices on first pass */
158     handleOnFirst = !strncmp(ptname, "md", 2);
159     if (firstPass != handleOnFirst)
160     continue;
161    
162     /* skip entire disk (minor 0, 64, ... on ide;
163     0, 16, ... on sd) */
164     /* heuristic: partition name ends in a digit */
165    
166     for(s = ptname; *s; s++);
167    
168     if (isdigit(s[-1])) {
169     char * ptr;
170     char * deviceDir = NULL;
171     int mustRemove = 0;
172     int mustRemoveDir = 0;
173     int i;
174    
175     sprintf(device, "%s/%s", DEVLABELDIR, ptname);
176     if (access(device, F_OK)) {
177     ptr = device;
178     i = 0;
179     while (*ptr)
180     if (*ptr++ == '/')
181     i++;
182     if (i > 2) {
183     deviceDir = alloca(strlen(device) + 1);
184     strcpy(deviceDir, device);
185     ptr = deviceDir + (strlen(device) - 1);
186     while (*ptr != '/')
187     *ptr-- = '\0';
188     if (mkdir(deviceDir, 0644)) {
189     printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
190     } else {
191     mustRemoveDir = 1;
192     }
193     }
194    
195     mknod(device, S_IFBLK | 0600, makedev(ma, mi));
196     mustRemove = 1;
197     }
198     if (!get_label_uuid(device, &label, uuid))
199     uuidcache_addentry(strdup(device), ma, mi,
200     label, uuid);
201    
202     if (mustRemove) unlink(device);
203     if (mustRemoveDir) rmdir(deviceDir);
204     }
205     }
206     }
207    
208     fclose(procpt);
209     }
210    
211     #define UUID 1
212     #define VOL 2
213    
214     static char *
215     get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) {
216     struct uuidCache_s *uc;
217    
218     uuidcache_init();
219     uc = uuidCache;
220    
221     while(uc) {
222     switch (n) {
223     case UUID:
224     if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
225     *majorPtr = uc->major;
226     *minorPtr = uc->minor;
227     return uc->device;
228     }
229     break;
230     case VOL:
231     if (!strcmp(t, uc->label)) {
232     *majorPtr = uc->major;
233     *minorPtr = uc->minor;
234     return uc->device;
235     }
236     break;
237     }
238     uc = uc->next;
239     }
240     return NULL;
241     }
242    
243     static unsigned char
244     fromhex(char c) {
245     if (isdigit(c))
246     return (c - '0');
247     else if (islower(c))
248     return (c - 'a' + 10);
249     else
250     return (c - 'A' + 10);
251     }
252    
253     char *
254     get_spec_by_uuid(const char *s, int * major, int * minor) {
255     unsigned char uuid[16];
256     int i;
257    
258     if (strlen(s) != 36 ||
259     s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
260     goto bad_uuid;
261     for (i=0; i<16; i++) {
262     if (*s == '-') s++;
263     if (!isxdigit(s[0]) || !isxdigit(s[1]))
264     goto bad_uuid;
265     uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
266     s += 2;
267     }
268     return get_spec_by_x(UUID, (char *)uuid, major, minor);
269    
270     bad_uuid:
271     fprintf(stderr, _("mount: bad UUID"));
272     return NULL;
273     }
274    
275     char *
276     get_spec_by_volume_label(const char *s, int * major, int * minor) {
277     return get_spec_by_x(VOL, s, major, minor);
278     }
279    
280     int
281     display_uuid_cache(char *cmd, char *end)
282     {
283     struct uuidCache_s * u;
284     size_t i;
285    
286     uuidcache_init();
287    
288     u = uuidCache;
289     while (u) {
290     printf("%s %s ", u->device, u->label);
291     for (i = 0; i < sizeof(u->uuid); i++) {
292     if (i == 4 || i == 6 || i == 8 || i == 10)
293     printf("-");
294     printf("%x", u->uuid[i] & 0xff);
295     }
296     printf("\n");
297     u = u->next;
298     }
299    
300     return 0;
301     }
302