1de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o/* 2de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * finddev.c -- this routine attempts to find a particular device in 3de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * /dev 4efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 5de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * Copyright (C) 2000 Theodore Ts'o. 6de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * 7de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * %Begin-Header% 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 9543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 10de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * %End-Header% 11de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 12de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 13de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <stdio.h> 14de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <string.h> 15de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#if HAVE_UNISTD_H 16de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <unistd.h> 17de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 18de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <stdlib.h> 19de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <string.h> 20de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#if HAVE_SYS_TYPES_H 21de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <sys/types.h> 22de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 23de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#if HAVE_SYS_STAT_H 24de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <sys/stat.h> 25de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 26de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <dirent.h> 27de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#if HAVE_ERRNO_H 28de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <errno.h> 29de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 30de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#if HAVE_SYS_MKDEV_H 31de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#include <sys/mkdev.h> 32de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 33de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 3431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o#include "ext2_fs.h" 3531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o#include "ext2fs.h" 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fsP.h" 3731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o 38de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'ostruct dir_list { 39de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o char *name; 40de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dir_list *next; 41de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o}; 42de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 43de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o/* 44de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * This function adds an entry to the directory list 45de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 4631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic void add_to_dirlist(const char *name, struct dir_list **list) 47de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o{ 48de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dir_list *dp; 49de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 50de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dp = malloc(sizeof(struct dir_list)); 51de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (!dp) 52de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return; 53de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dp->name = malloc(strlen(name)+1); 54de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (!dp->name) { 55de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(dp); 56de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return; 57de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 58de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o strcpy(dp->name, name); 59de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dp->next = *list; 60de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o *list = dp; 61de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o} 62de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 63de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o/* 64de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * This function frees a directory list 65de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 66de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'ostatic void free_dirlist(struct dir_list **list) 67de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o{ 68de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dir_list *dp, *next; 69de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 70de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o for (dp = *list; dp; dp = next) { 71de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o next = dp->next; 72de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(dp->name); 73de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(dp); 74de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 75de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o *list = 0; 76de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o} 77de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 78de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'ostatic int scan_dir(char *dirname, dev_t device, struct dir_list **list, 79de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o char **ret_path) 80de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o{ 81de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o DIR *dir; 82de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dirent *dp; 83de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o char path[1024], *cp; 84de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o int dirlen; 85de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct stat st; 86de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 87de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dirlen = strlen(dirname); 88de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if ((dir = opendir(dirname)) == NULL) 89de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return errno; 90de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dp = readdir(dir); 91de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o while (dp) { 92de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) 93de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o goto skip_to_next; 94de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (dp->d_name[0] == '.' && 95de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o ((dp->d_name[1] == 0) || 9631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) 97de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o goto skip_to_next; 98de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o sprintf(path, "%s/%s", dirname, dp->d_name); 99de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (stat(path, &st) < 0) 100f86fa6c7483f6fee33fb128fced4644ec876a1bcTheodore Ts'o goto skip_to_next; 101de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (S_ISDIR(st.st_mode)) 102de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o add_to_dirlist(path, list); 103de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (S_ISBLK(st.st_mode) && st.st_rdev == device) { 104de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o cp = malloc(strlen(path)+1); 1053751721fbb2b72cf99dff3755249357ef5372205Theodore Ts'o if (!cp) { 1063751721fbb2b72cf99dff3755249357ef5372205Theodore Ts'o closedir(dir); 107de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return ENOMEM; 1083751721fbb2b72cf99dff3755249357ef5372205Theodore Ts'o } 109de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o strcpy(cp, path); 110de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o *ret_path = cp; 1113751721fbb2b72cf99dff3755249357ef5372205Theodore Ts'o goto success; 112de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 113de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o skip_to_next: 114de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dp = readdir(dir); 115de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 1163751721fbb2b72cf99dff3755249357ef5372205Theodore Ts'osuccess: 117de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o closedir(dir); 118de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return 0; 119de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o} 120de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 121de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o/* 122de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * This function finds the pathname to a block device with a given 123de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * device number. It returns a pointer to allocated memory to the 124de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * pathname on success, and NULL on failure. 125de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 126de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'ochar *ext2fs_find_block_device(dev_t device) 127de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o{ 128de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dir_list *list = 0, *new_list = 0; 129de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o struct dir_list *current; 130de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o char *ret_path = 0; 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int level = 0; 132de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 133de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o /* 134de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * Add the starting directories to search... 135de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 136de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o add_to_dirlist("/devices", &list); 137de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o add_to_dirlist("/devfs", &list); 138de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o add_to_dirlist("/dev", &list); 139efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 140de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o while (list) { 141de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o current = list; 142de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o list = list->next; 143de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#ifdef DEBUG 144de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o printf("Scanning directory %s\n", current->name); 145de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 146de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o scan_dir(current->name, device, &new_list, &ret_path); 147de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(current->name); 148de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(current); 149de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (ret_path) 150de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o break; 151de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o /* 152de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * If we're done checking at this level, descend to 153de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o * the next level of subdirectories. (breadth-first) 154de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o */ 155de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (list == 0) { 156de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o list = new_list; 157de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o new_list = 0; 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Avoid infinite loop */ 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (++level >= EXT2FS_MAX_NESTED_LINKS) 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 161de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 162de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 163de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free_dirlist(&list); 164de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free_dirlist(&new_list); 165de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return ret_path; 166de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o} 167de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 168efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 169de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#ifdef DEBUG 170de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'oint main(int argc, char** argv) 171de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o{ 172de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o char *devname, *tmp; 173de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o int major, minor; 174de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o dev_t device; 175de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o const char *errmsg = "Couldn't parse %s: %s\n"; 176de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o 177de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if ((argc != 2) && (argc != 3)) { 178de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o fprintf(stderr, "Usage: %s device_number\n", argv[0]); 179de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o fprintf(stderr, "\t: %s major minor\n", argv[0]); 180de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o exit(1); 181de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 182de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (argc == 2) { 183de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o device = strtoul(argv[1], &tmp, 0); 184de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (*tmp) { 185de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o fprintf(stderr, errmsg, "device number", argv[1]); 186de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o exit(1); 187de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 188de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } else { 189de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o major = strtoul(argv[1], &tmp, 0); 190de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (*tmp) { 191de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o fprintf(stderr, errmsg, "major number", argv[1]); 192de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o exit(1); 193de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 194de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o minor = strtoul(argv[2], &tmp, 0); 195de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (*tmp) { 196de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o fprintf(stderr, errmsg, "minor number", argv[2]); 197de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o exit(1); 198de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 199de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o device = makedev(major, minor); 200de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o printf("Looking for device 0x%04x (%d:%d)\n", device, 201de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o major, minor); 202de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 203de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o devname = ext2fs_find_block_device(device); 204de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o if (devname) { 205de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o printf("Found device! %s\n", devname); 206de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o free(devname); 207de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } else { 208de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o printf("Couldn't find device.\n"); 209de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o } 210de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o return 0; 211de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o} 212efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 213de23aa1d177a67283f5f5a1f172b00527fe3b63aTheodore Ts'o#endif 214