Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 8588 byte(s)
-updated to busybox-1.17.1
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * devname.c - get a dev by its device inode name
4     *
5     * Copyright (C) Andries Brouwer
6     * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
7     * Copyright (C) 2001 Andreas Dilger
8     *
9     * %Begin-Header%
10     * This file may be redistributed under the terms of the
11     * GNU Lesser General Public License.
12     * %End-Header%
13     */
14    
15     #include <stdio.h>
16     #include <string.h>
17     #ifdef HAVE_UNISTD_H
18     #include <unistd.h>
19     #endif
20     #include <stdlib.h>
21     #include <string.h>
22     #include <ctype.h>
23     #ifdef HAVE_SYS_TYPES_H
24     #include <sys/types.h>
25     #endif
26     #include <sys/stat.h>
27     #ifdef HAVE_ERRNO_H
28     #include <errno.h>
29     #endif
30     #ifdef HAVE_SYS_MKDEV_H
31     #include <sys/mkdev.h>
32     #endif
33     #include <time.h>
34    
35     #include "blkidP.h"
36    
37     /*
38     * Find a dev struct in the cache by device name, if available.
39     *
40     * If there is no entry with the specified device name, and the create
41     * flag is set, then create an empty device entry.
42     */
43     blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
44     {
45     blkid_dev dev = NULL, tmp;
46     struct list_head *p;
47    
48     if (!cache || !devname)
49     return NULL;
50    
51     list_for_each(p, &cache->bic_devs) {
52     tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
53     if (strcmp(tmp->bid_name, devname))
54     continue;
55    
56     DBG(DEBUG_DEVNAME,
57     printf("found devname %s in cache\n", tmp->bid_name));
58     dev = tmp;
59     break;
60     }
61    
62     if (!dev && (flags & BLKID_DEV_CREATE)) {
63     dev = blkid_new_dev();
64     if (!dev)
65     return NULL;
66     dev->bid_name = blkid_strdup(devname);
67     dev->bid_cache = cache;
68     list_add_tail(&dev->bid_devs, &cache->bic_devs);
69     cache->bic_flags |= BLKID_BIC_FL_CHANGED;
70     }
71    
72     if (flags & BLKID_DEV_VERIFY)
73     dev = blkid_verify(cache, dev);
74     return dev;
75     }
76    
77     /*
78     * Probe a single block device to add to the device cache.
79     */
80     static void probe_one(blkid_cache cache, const char *ptname,
81     dev_t devno, int pri)
82     {
83     blkid_dev dev = NULL;
84     struct list_head *p;
85     const char **dir;
86     char *devname = NULL;
87    
88     /* See if we already have this device number in the cache. */
89     list_for_each(p, &cache->bic_devs) {
90     blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
91     bid_devs);
92     if (tmp->bid_devno == devno) {
93     dev = blkid_verify(cache, tmp);
94     break;
95     }
96     }
97     if (dev && dev->bid_devno == devno)
98     goto set_pri;
99    
100     /*
101     * Take a quick look at /dev/ptname for the device number. We check
102     * all of the likely device directories. If we don't find it, or if
103     * the stat information doesn't check out, use blkid_devno_to_devname()
104     * to find it via an exhaustive search for the device major/minor.
105     */
106     for (dir = blkid_devdirs; *dir; dir++) {
107     struct stat st;
108     char device[256];
109    
110     sprintf(device, "%s/%s", *dir, ptname);
111     if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
112     dev->bid_devno == devno)
113     goto set_pri;
114    
115     if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
116     st.st_rdev == devno) {
117     devname = blkid_strdup(device);
118     break;
119     }
120     }
121     if (!devname) {
122     devname = blkid_devno_to_devname(devno);
123     if (!devname)
124     return;
125     }
126     dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
127     free(devname);
128    
129     set_pri:
130     if (!pri && !strncmp(ptname, "md", 2))
131     pri = BLKID_PRI_MD;
132     if (dev)
133     dev->bid_pri = pri;
134     }
135    
136     #define PROC_PARTITIONS "/proc/partitions"
137     #define VG_DIR "/proc/lvm/VGs"
138    
139     /*
140     * This function initializes the UUID cache with devices from the LVM
141     * proc hierarchy. We currently depend on the names of the LVM
142     * hierarchy giving us the device structure in /dev. (XXX is this a
143     * safe thing to do?)
144     */
145     #ifdef VG_DIR
146     #include <dirent.h>
147     static dev_t lvm_get_devno(const char *lvm_device)
148     {
149     FILE *lvf;
150     char buf[1024];
151     int ma, mi;
152     dev_t ret = 0;
153    
154     DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
155 niro 816 if ((lvf = fopen_for_read(lvm_device)) == NULL) {
156 niro 532 DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
157     strerror(errno)));
158     return 0;
159     }
160    
161     while (fgets(buf, sizeof(buf), lvf)) {
162     if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
163     ret = makedev(ma, mi);
164     break;
165     }
166     }
167     fclose(lvf);
168    
169     return ret;
170     }
171    
172     static void lvm_probe_all(blkid_cache cache)
173     {
174     DIR *vg_list;
175     struct dirent *vg_iter;
176     int vg_len = strlen(VG_DIR);
177     dev_t dev;
178    
179     if ((vg_list = opendir(VG_DIR)) == NULL)
180     return;
181    
182     DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
183    
184     while ((vg_iter = readdir(vg_list)) != NULL) {
185     DIR *lv_list;
186     char *vdirname;
187     char *vg_name;
188     struct dirent *lv_iter;
189    
190     vg_name = vg_iter->d_name;
191     if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, ".."))
192     continue;
193     vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
194     sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
195    
196     lv_list = opendir(vdirname);
197     free(vdirname);
198     if (lv_list == NULL)
199     continue;
200    
201     while ((lv_iter = readdir(lv_list)) != NULL) {
202     char *lv_name, *lvm_device;
203    
204     lv_name = lv_iter->d_name;
205     if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, ".."))
206     continue;
207    
208     lvm_device = xmalloc(vg_len + strlen(vg_name) +
209     strlen(lv_name) + 8);
210     sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
211     lv_name);
212     dev = lvm_get_devno(lvm_device);
213     sprintf(lvm_device, "%s/%s", vg_name, lv_name);
214     DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
215     lvm_device,
216     (unsigned int) dev));
217     probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
218     free(lvm_device);
219     }
220     closedir(lv_list);
221     }
222     closedir(vg_list);
223     }
224     #endif
225    
226     #define PROC_EVMS_VOLUMES "/proc/evms/volumes"
227    
228     static int
229     evms_probe_all(blkid_cache cache)
230     {
231     char line[100];
232     int ma, mi, sz, num = 0;
233     FILE *procpt;
234     char device[110];
235    
236 niro 816 procpt = fopen_for_read(PROC_EVMS_VOLUMES);
237 niro 532 if (!procpt)
238     return 0;
239     while (fgets(line, sizeof(line), procpt)) {
240 niro 816 if (sscanf(line, " %d %d %d %*s %*s %[^\n ]",
241 niro 532 &ma, &mi, &sz, device) != 4)
242     continue;
243    
244     DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
245     device, ma, mi));
246    
247     probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
248     num++;
249     }
250     fclose(procpt);
251     return num;
252     }
253    
254     /*
255     * Read the device data for all available block devices in the system.
256     */
257     int blkid_probe_all(blkid_cache cache)
258     {
259     FILE *proc;
260     char line[1024];
261 niro 1123 char ptname0[128], ptname1[128], *ptname = NULL;
262 niro 532 char *ptnames[2];
263     dev_t devs[2];
264     int ma, mi;
265     unsigned long long sz;
266     int lens[2] = { 0, 0 };
267     int which = 0, last = 0;
268    
269     ptnames[0] = ptname0;
270     ptnames[1] = ptname1;
271    
272     if (!cache)
273     return -BLKID_ERR_PARAM;
274    
275     if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
276 niro 984 time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL)
277 niro 532 return 0;
278    
279     blkid_read_cache(cache);
280     evms_probe_all(cache);
281     #ifdef VG_DIR
282     lvm_probe_all(cache);
283     #endif
284    
285 niro 816 proc = fopen_for_read(PROC_PARTITIONS);
286 niro 532 if (!proc)
287     return -BLKID_ERR_PROC;
288    
289     while (fgets(line, sizeof(line), proc)) {
290     last = which;
291     which ^= 1;
292     ptname = ptnames[which];
293    
294     if (sscanf(line, " %d %d %llu %128[^\n ]",
295     &ma, &mi, &sz, ptname) != 4)
296     continue;
297     devs[which] = makedev(ma, mi);
298    
299     DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
300    
301     /* Skip whole disk devs unless they have no partitions
302     * If we don't have a partition on this dev, also
303     * check previous dev to see if it didn't have a partn.
304     * heuristic: partition name ends in a digit.
305     *
306     * Skip extended partitions.
307     * heuristic: size is 1
308     *
309     * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
310     */
311    
312     lens[which] = strlen(ptname);
313     if (isdigit(ptname[lens[which] - 1])) {
314     DBG(DEBUG_DEVNAME,
315     printf("partition dev %s, devno 0x%04X\n",
316     ptname, (unsigned int) devs[which]));
317    
318     if (sz > 1)
319     probe_one(cache, ptname, devs[which], 0);
320     lens[which] = 0;
321     lens[last] = 0;
322     } else if (lens[last] && strncmp(ptnames[last], ptname,
323     lens[last])) {
324     DBG(DEBUG_DEVNAME,
325     printf("whole dev %s, devno 0x%04X\n",
326     ptnames[last], (unsigned int) devs[last]));
327     probe_one(cache, ptnames[last], devs[last], 0);
328     lens[last] = 0;
329     }
330     }
331    
332     /* Handle the last device if it wasn't partitioned */
333     if (lens[which])
334     probe_one(cache, ptname, devs[which], 0);
335    
336     fclose(proc);
337    
338 niro 984 cache->bic_time = time(NULL);
339 niro 532 cache->bic_flags |= BLKID_BIC_FL_PROBED;
340     blkid_flush_cache(cache);
341     return 0;
342     }
343    
344     #ifdef TEST_PROGRAM
345     int main(int argc, char **argv)
346     {
347     blkid_cache cache = NULL;
348     int ret;
349    
350     blkid_debug_mask = DEBUG_ALL;
351     if (argc != 1) {
352     fprintf(stderr, "Usage: %s\n"
353     "Probe all devices and exit\n", argv[0]);
354     exit(1);
355     }
356     if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
357     fprintf(stderr, "%s: error creating cache (%d)\n",
358     argv[0], ret);
359     exit(1);
360     }
361     if (blkid_probe_all(cache) < 0)
362     printf("%s: error probing devices\n", argv[0]);
363    
364     blkid_put_cache(cache);
365     return 0;
366     }
367     #endif