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