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