source: branches/stable/mindi-busybox/e2fsprogs/blkid/devno.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.6 KB
RevLine 
[821]1/*
2 * devno.c - find a particular device by its device number (major/minor)
3 *
4 * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
5 * Copyright (C) 2001 Andreas Dilger
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 * %End-Header%
11 */
12
13#include <stdio.h>
14#include <string.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <stdlib.h>
19#include <string.h>
20#if HAVE_SYS_TYPES_H
21#include <sys/types.h>
22#endif
23#if HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#include <dirent.h>
27#if HAVE_ERRNO_H
28#include <errno.h>
29#endif
30#if HAVE_SYS_MKDEV_H
31#include <sys/mkdev.h>
32#endif
33
34#include "blkidP.h"
35
36struct dir_list {
37    char    *name;
38    struct dir_list *next;
39};
40
41char *blkid_strndup(const char *s, int length)
42{
43    char *ret;
44
45    if (!s)
46        return NULL;
47
48    if (!length)
49        length = strlen(s);
50
51    ret = xmalloc(length + 1);
52    strncpy(ret, s, length);
53    ret[length] = '\0';
54    return ret;
55}
56
57char *blkid_strdup(const char *s)
58{
59    return blkid_strndup(s, 0);
60}
61
62/*
63 * This function adds an entry to the directory list
64 */
65static void add_to_dirlist(const char *name, struct dir_list **list)
66{
67    struct dir_list *dp;
68
69    dp = xmalloc(sizeof(struct dir_list));
70    dp->name = blkid_strdup(name);
71    dp->next = *list;
72    *list = dp;
73}
74
75/*
76 * This function frees a directory list
77 */
78static void free_dirlist(struct dir_list **list)
79{
80    struct dir_list *dp, *next;
81
82    for (dp = *list; dp; dp = next) {
83        next = dp->next;
84        free(dp->name);
85        free(dp);
86    }
87    *list = NULL;
88}
89
90static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
91                char **devname)
92{
93    DIR *dir;
94    struct dirent *dp;
95    char    path[1024];
96    int dirlen;
97    struct stat st;
98
99    if ((dir = opendir(dir_name)) == NULL)
100        return;
101    dirlen = strlen(dir_name) + 2;
102    while ((dp = readdir(dir)) != 0) {
103        if (dirlen + strlen(dp->d_name) >= sizeof(path))
104            continue;
105
106        if (dp->d_name[0] == '.' &&
107            ((dp->d_name[1] == 0) ||
108             ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
109            continue;
110
111        sprintf(path, "%s/%s", dir_name, dp->d_name);
112        if (stat(path, &st) < 0)
113            continue;
114
115        if (S_ISDIR(st.st_mode))
116            add_to_dirlist(path, list);
117        else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
118            *devname = blkid_strdup(path);
119            DBG(DEBUG_DEVNO,
120                printf("found 0x%llx at %s (%p)\n", devno,
121                   path, *devname));
122            break;
123        }
124    }
125    closedir(dir);
126    return;
127}
128
129/* Directories where we will try to search for device numbers */
130const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
131
132/*
133 * This function finds the pathname to a block device with a given
134 * device number.  It returns a pointer to allocated memory to the
135 * pathname on success, and NULL on failure.
136 */
137char *blkid_devno_to_devname(dev_t devno)
138{
139    struct dir_list *list = NULL, *new_list = NULL;
140    char *devname = NULL;
141    const char **dir;
142
143    /*
144     * Add the starting directories to search in reverse order of
145     * importance, since we are using a stack...
146     */
147    for (dir = blkid_devdirs; *dir; dir++)
148        add_to_dirlist(*dir, &list);
149
150    while (list) {
151        struct dir_list *current = list;
152
153        list = list->next;
154        DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
155        scan_dir(current->name, devno, &new_list, &devname);
156        free(current->name);
157        free(current);
158        if (devname)
159            break;
160        /*
161         * If we're done checking at this level, descend to
162         * the next level of subdirectories. (breadth-first)
163         */
164        if (list == NULL) {
165            list = new_list;
166            new_list = NULL;
167        }
168    }
169    free_dirlist(&list);
170    free_dirlist(&new_list);
171
172    if (!devname) {
173        DBG(DEBUG_DEVNO,
174            printf("blkid: couldn't find devno 0x%04lx\n",
175               (unsigned long) devno));
176    } else {
177        DBG(DEBUG_DEVNO,
178            printf("found devno 0x%04llx as %s\n", devno, devname));
179    }
180
181
182    return devname;
183}
184
185#ifdef TEST_PROGRAM
186int main(int argc, char** argv)
187{
188    char    *devname, *tmp;
189    int major, minor;
190    dev_t   devno;
191    const char *errmsg = "Couldn't parse %s: %s\n";
192
193    blkid_debug_mask = DEBUG_ALL;
194    if ((argc != 2) && (argc != 3)) {
195        fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
196            "Resolve a device number to a device name\n",
197            argv[0], argv[0]);
198        exit(1);
199    }
200    if (argc == 2) {
201        devno = strtoul(argv[1], &tmp, 0);
202        if (*tmp) {
203            fprintf(stderr, errmsg, "device number", argv[1]);
204            exit(1);
205        }
206    } else {
207        major = strtoul(argv[1], &tmp, 0);
208        if (*tmp) {
209            fprintf(stderr, errmsg, "major number", argv[1]);
210            exit(1);
211        }
212        minor = strtoul(argv[2], &tmp, 0);
213        if (*tmp) {
214            fprintf(stderr, errmsg, "minor number", argv[2]);
215            exit(1);
216        }
217        devno = makedev(major, minor);
218    }
219    printf("Looking for device 0x%04Lx\n", devno);
220    devname = blkid_devno_to_devname(devno);
221    free(devname);
222    return 0;
223}
224#endif
Note: See TracBrowser for help on using the repository browser.