blob: 552aa79c3994bcd3ca19db675e5578d382436a87 [file] [log] [blame]
Mike Frysinger1fd98e02005-05-09 22:10:42 +00001/*
2 * finddev.c -- this routine attempts to find a particular device in
Tim Rikerc1ef7bd2006-01-25 00:08:53 +00003 * /dev
4 *
Mike Frysinger1fd98e02005-05-09 22:10:42 +00005 * Copyright (C) 2000 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * 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 "ext2_fs.h"
35#include "ext2fs.h"
36
37struct dir_list {
38 char *name;
39 struct dir_list *next;
40};
41
42/*
43 * This function adds an entry to the directory list
44 */
45static void add_to_dirlist(const char *name, struct dir_list **list)
46{
47 struct dir_list *dp;
48
Mike Frysingerd5826902005-06-12 00:45:09 +000049 dp = xmalloc(sizeof(struct dir_list));
50 dp->name = xmalloc(strlen(name)+1);
Mike Frysinger1fd98e02005-05-09 22:10:42 +000051 strcpy(dp->name, name);
52 dp->next = *list;
53 *list = dp;
54}
55
56/*
57 * This function frees a directory list
58 */
59static void free_dirlist(struct dir_list **list)
60{
61 struct dir_list *dp, *next;
62
63 for (dp = *list; dp; dp = next) {
64 next = dp->next;
65 free(dp->name);
66 free(dp);
67 }
68 *list = 0;
69}
70
71static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
72 char **ret_path)
73{
74 DIR *dir;
75 struct dirent *dp;
76 char path[1024], *cp;
77 int dirlen;
78 struct stat st;
79
80 dirlen = strlen(dir_name);
81 if ((dir = opendir(dir_name)) == NULL)
82 return errno;
83 dp = readdir(dir);
84 while (dp) {
85 if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
86 goto skip_to_next;
87 if (dp->d_name[0] == '.' &&
88 ((dp->d_name[1] == 0) ||
89 ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
90 goto skip_to_next;
91 sprintf(path, "%s/%s", dir_name, dp->d_name);
92 if (stat(path, &st) < 0)
93 goto skip_to_next;
94 if (S_ISDIR(st.st_mode))
95 add_to_dirlist(path, list);
96 if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
Mike Frysingerd5826902005-06-12 00:45:09 +000097 cp = xmalloc(strlen(path)+1);
Mike Frysinger1fd98e02005-05-09 22:10:42 +000098 strcpy(cp, path);
99 *ret_path = cp;
100 goto success;
101 }
102 skip_to_next:
103 dp = readdir(dir);
104 }
105success:
106 closedir(dir);
107 return 0;
108}
109
110/*
111 * This function finds the pathname to a block device with a given
112 * device number. It returns a pointer to allocated memory to the
113 * pathname on success, and NULL on failure.
114 */
115char *ext2fs_find_block_device(dev_t device)
116{
117 struct dir_list *list = 0, *new_list = 0;
118 struct dir_list *current;
119 char *ret_path = 0;
120
121 /*
122 * Add the starting directories to search...
123 */
124 add_to_dirlist("/devices", &list);
125 add_to_dirlist("/devfs", &list);
126 add_to_dirlist("/dev", &list);
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000127
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000128 while (list) {
129 current = list;
130 list = list->next;
131#ifdef DEBUG
132 printf("Scanning directory %s\n", current->name);
133#endif
134 scan_dir(current->name, device, &new_list, &ret_path);
135 free(current->name);
136 free(current);
137 if (ret_path)
138 break;
139 /*
140 * If we're done checking at this level, descend to
141 * the next level of subdirectories. (breadth-first)
142 */
143 if (list == 0) {
144 list = new_list;
145 new_list = 0;
146 }
147 }
148 free_dirlist(&list);
149 free_dirlist(&new_list);
150 return ret_path;
151}
152
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000153
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000154#ifdef DEBUG
155int main(int argc, char** argv)
156{
157 char *devname, *tmp;
158 int major, minor;
159 dev_t device;
160 const char *errmsg = "Couldn't parse %s: %s\n";
161
162 if ((argc != 2) && (argc != 3)) {
163 fprintf(stderr, "Usage: %s device_number\n", argv[0]);
164 fprintf(stderr, "\t: %s major minor\n", argv[0]);
165 exit(1);
166 }
167 if (argc == 2) {
168 device = strtoul(argv[1], &tmp, 0);
169 if (*tmp) {
170 fprintf(stderr, errmsg, "device number", argv[1]);
171 exit(1);
172 }
173 } else {
174 major = strtoul(argv[1], &tmp, 0);
175 if (*tmp) {
176 fprintf(stderr, errmsg, "major number", argv[1]);
177 exit(1);
178 }
179 minor = strtoul(argv[2], &tmp, 0);
180 if (*tmp) {
181 fprintf(stderr, errmsg, "minor number", argv[2]);
182 exit(1);
183 }
184 device = makedev(major, minor);
185 printf("Looking for device 0x%04x (%d:%d)\n", device,
186 major, minor);
187 }
188 devname = ext2fs_find_block_device(device);
189 if (devname) {
190 printf("Found device! %s\n", devname);
191 free(devname);
192 } else {
193 printf("Couldn't find device.\n");
194 }
195 return 0;
196}
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000197
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000198#endif