devno.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. #include <stdio.h>
  14. #include <string.h>
  15. #ifdef HAVE_UNISTD_H
  16. #include <unistd.h>
  17. #endif
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #ifdef HAVE_SYS_TYPES_H
  21. #include <sys/types.h>
  22. #endif
  23. #include <sys/stat.h>
  24. #include <dirent.h>
  25. #ifdef HAVE_ERRNO_H
  26. #include <errno.h>
  27. #endif
  28. #ifdef HAVE_SYS_MKDEV_H
  29. #include <sys/mkdev.h>
  30. #endif
  31. #include "blkidP.h"
  32. struct dir_list {
  33. char *name;
  34. struct dir_list *next;
  35. };
  36. char *blkid_strndup(const char *s, int length)
  37. {
  38. char *ret;
  39. if (!s)
  40. return NULL;
  41. if (!length)
  42. length = strlen(s);
  43. ret = xmalloc(length + 1);
  44. strncpy(ret, s, length);
  45. ret[length] = '\0';
  46. return ret;
  47. }
  48. char *blkid_strdup(const char *s)
  49. {
  50. return blkid_strndup(s, 0);
  51. }
  52. /*
  53. * This function adds an entry to the directory list
  54. */
  55. static void add_to_dirlist(const char *name, struct dir_list **list)
  56. {
  57. struct dir_list *dp;
  58. dp = xmalloc(sizeof(struct dir_list));
  59. dp->name = blkid_strdup(name);
  60. dp->next = *list;
  61. *list = dp;
  62. }
  63. /*
  64. * This function frees a directory list
  65. */
  66. static void free_dirlist(struct dir_list **list)
  67. {
  68. struct dir_list *dp, *next;
  69. for (dp = *list; dp; dp = next) {
  70. next = dp->next;
  71. free(dp->name);
  72. free(dp);
  73. }
  74. *list = NULL;
  75. }
  76. static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
  77. char **devname)
  78. {
  79. DIR *dir;
  80. struct dirent *dp;
  81. char path[1024];
  82. int dirlen;
  83. struct stat st;
  84. if ((dir = opendir(dir_name)) == NULL)
  85. return;
  86. dirlen = strlen(dir_name) + 2;
  87. while ((dp = readdir(dir)) != 0) {
  88. if (dirlen + strlen(dp->d_name) >= sizeof(path))
  89. continue;
  90. if (dp->d_name[0] == '.' &&
  91. ((dp->d_name[1] == 0) ||
  92. ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
  93. continue;
  94. sprintf(path, "%s/%s", dir_name, dp->d_name);
  95. if (stat(path, &st) < 0)
  96. continue;
  97. if (S_ISDIR(st.st_mode))
  98. add_to_dirlist(path, list);
  99. else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
  100. *devname = blkid_strdup(path);
  101. DBG(DEBUG_DEVNO,
  102. printf("found 0x%llx at %s (%p)\n", devno,
  103. path, *devname));
  104. break;
  105. }
  106. }
  107. closedir(dir);
  108. }
  109. /* Directories where we will try to search for device numbers */
  110. const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
  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. */
  116. char *blkid_devno_to_devname(dev_t devno)
  117. {
  118. struct dir_list *list = NULL, *new_list = NULL;
  119. char *devname = NULL;
  120. const char **dir;
  121. /*
  122. * Add the starting directories to search in reverse order of
  123. * importance, since we are using a stack...
  124. */
  125. for (dir = blkid_devdirs; *dir; dir++)
  126. add_to_dirlist(*dir, &list);
  127. while (list) {
  128. struct dir_list *current = list;
  129. list = list->next;
  130. DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
  131. scan_dir(current->name, devno, &new_list, &devname);
  132. free(current->name);
  133. free(current);
  134. if (devname)
  135. break;
  136. /*
  137. * If we're done checking at this level, descend to
  138. * the next level of subdirectories. (breadth-first)
  139. */
  140. if (list == NULL) {
  141. list = new_list;
  142. new_list = NULL;
  143. }
  144. }
  145. free_dirlist(&list);
  146. free_dirlist(&new_list);
  147. if (!devname) {
  148. DBG(DEBUG_DEVNO,
  149. printf("blkid: cannot find devno 0x%04lx\n",
  150. (unsigned long) devno));
  151. } else {
  152. DBG(DEBUG_DEVNO,
  153. printf("found devno 0x%04llx as %s\n", devno, devname));
  154. }
  155. return devname;
  156. }
  157. #ifdef TEST_PROGRAM
  158. int main(int argc, char** argv)
  159. {
  160. char *devname, *tmp;
  161. int major, minor;
  162. dev_t devno;
  163. const char *errmsg = "Cannot parse %s: %s\n";
  164. blkid_debug_mask = DEBUG_ALL;
  165. if ((argc != 2) && (argc != 3)) {
  166. fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
  167. "Resolve a device number to a device name\n",
  168. argv[0], argv[0]);
  169. exit(1);
  170. }
  171. if (argc == 2) {
  172. devno = strtoul(argv[1], &tmp, 0);
  173. if (*tmp) {
  174. fprintf(stderr, errmsg, "device number", argv[1]);
  175. exit(1);
  176. }
  177. } else {
  178. major = strtoul(argv[1], &tmp, 0);
  179. if (*tmp) {
  180. fprintf(stderr, errmsg, "major number", argv[1]);
  181. exit(1);
  182. }
  183. minor = strtoul(argv[2], &tmp, 0);
  184. if (*tmp) {
  185. fprintf(stderr, errmsg, "minor number", argv[2]);
  186. exit(1);
  187. }
  188. devno = makedev(major, minor);
  189. }
  190. printf("Looking for device 0x%04Lx\n", devno);
  191. devname = blkid_devno_to_devname(devno);
  192. free(devname);
  193. return 0;
  194. }
  195. #endif