1 /* vi: set sw=4 ts=4: */ 2 /* 3 * Utility routines. 4 * 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 */ 9 #include "libbb.h" 10 11 /* Find block device /dev/XXX which contains specified file 12 * We handle /dev/dir/dir/dir too, at a cost of ~80 more bytes code */ 13 14 /* Do not reallocate all this stuff on each recursion */ 15 enum { DEVNAME_MAX = 256 }; 16 struct arena { 17 struct stat st; 18 dev_t dev; 19 /* Was PATH_MAX, but we recurse _/dev_. We can assume 20 * people are not crazy enough to have mega-deep tree there */ 21 char devpath[DEVNAME_MAX]; 22 }; 23 find_block_device_in_dir(struct arena * ap)24static char *find_block_device_in_dir(struct arena *ap) 25 { 26 DIR *dir; 27 struct dirent *entry; 28 char *retpath = NULL; 29 int len, rem; 30 31 len = strlen(ap->devpath); 32 rem = DEVNAME_MAX-2 - len; 33 if (rem <= 0) 34 return NULL; 35 36 dir = opendir(ap->devpath); 37 if (!dir) 38 return NULL; 39 40 ap->devpath[len++] = '/'; 41 42 while ((entry = readdir(dir)) != NULL) { 43 safe_strncpy(ap->devpath + len, entry->d_name, rem); 44 /* lstat: do not follow links */ 45 if (lstat(ap->devpath, &ap->st) != 0) 46 continue; 47 if (S_ISBLK(ap->st.st_mode) && ap->st.st_rdev == ap->dev) { 48 retpath = xstrdup(ap->devpath); 49 break; 50 } 51 if (S_ISDIR(ap->st.st_mode)) { 52 /* Do not recurse for '.' and '..' */ 53 if (DOT_OR_DOTDOT(entry->d_name)) 54 continue; 55 retpath = find_block_device_in_dir(ap); 56 if (retpath) 57 break; 58 } 59 } 60 closedir(dir); 61 62 return retpath; 63 } 64 find_block_device(const char * path)65char* FAST_FUNC find_block_device(const char *path) 66 { 67 struct arena a; 68 69 if (stat(path, &a.st) != 0) 70 return NULL; 71 a.dev = S_ISBLK(a.st.st_mode) ? a.st.st_rdev : a.st.st_dev; 72 strcpy(a.devpath, "/dev"); 73 return find_block_device_in_dir(&a); 74 } 75