• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/router/busybox-1.x/e2fsprogs/old_e2fsprogs/blkid/
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
35struct dir_list {
36	char	*name;
37	struct dir_list *next;
38};
39
40char *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
56char *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 */
64static 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 */
77static 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
89static 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}
126
127/* Directories where we will try to search for device numbers */
128const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
129
130/*
131 * This function finds the pathname to a block device with a given
132 * device number.  It returns a pointer to allocated memory to the
133 * pathname on success, and NULL on failure.
134 */
135char *blkid_devno_to_devname(dev_t devno)
136{
137	struct dir_list *list = NULL, *new_list = NULL;
138	char *devname = NULL;
139	const char **dir;
140
141	/*
142	 * Add the starting directories to search in reverse order of
143	 * importance, since we are using a stack...
144	 */
145	for (dir = blkid_devdirs; *dir; dir++)
146		add_to_dirlist(*dir, &list);
147
148	while (list) {
149		struct dir_list *current = list;
150
151		list = list->next;
152		DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
153		scan_dir(current->name, devno, &new_list, &devname);
154		free(current->name);
155		free(current);
156		if (devname)
157			break;
158		/*
159		 * If we're done checking at this level, descend to
160		 * the next level of subdirectories. (breadth-first)
161		 */
162		if (list == NULL) {
163			list = new_list;
164			new_list = NULL;
165		}
166	}
167	free_dirlist(&list);
168	free_dirlist(&new_list);
169
170	if (!devname) {
171		DBG(DEBUG_DEVNO,
172		    printf("blkid: cannot find devno 0x%04lx\n",
173			   (unsigned long) devno));
174	} else {
175		DBG(DEBUG_DEVNO,
176		    printf("found devno 0x%04llx as %s\n", devno, devname));
177	}
178
179
180	return devname;
181}
182
183#ifdef TEST_PROGRAM
184int main(int argc, char** argv)
185{
186	char	*devname, *tmp;
187	int	major, minor;
188	dev_t	devno;
189	const char *errmsg = "Cannot parse %s: %s\n";
190
191	blkid_debug_mask = DEBUG_ALL;
192	if ((argc != 2) && (argc != 3)) {
193		fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
194			"Resolve a device number to a device name\n",
195			argv[0], argv[0]);
196		exit(1);
197	}
198	if (argc == 2) {
199		devno = strtoul(argv[1], &tmp, 0);
200		if (*tmp) {
201			fprintf(stderr, errmsg, "device number", argv[1]);
202			exit(1);
203		}
204	} else {
205		major = strtoul(argv[1], &tmp, 0);
206		if (*tmp) {
207			fprintf(stderr, errmsg, "major number", argv[1]);
208			exit(1);
209		}
210		minor = strtoul(argv[2], &tmp, 0);
211		if (*tmp) {
212			fprintf(stderr, errmsg, "minor number", argv[2]);
213			exit(1);
214		}
215		devno = makedev(major, minor);
216	}
217	printf("Looking for device 0x%04Lx\n", devno);
218	devname = blkid_devno_to_devname(devno);
219	free(devname);
220	return 0;
221}
222#endif
223