fs.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* TODO merge/factor in debugfs.c here */
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/vfs.h>
  9. #include "debugfs.h"
  10. #include "fs.h"
  11. static const char * const sysfs__fs_known_mountpoints[] = {
  12. "/sys",
  13. 0,
  14. };
  15. static const char * const procfs__known_mountpoints[] = {
  16. "/proc",
  17. 0,
  18. };
  19. struct fs {
  20. const char *name;
  21. const char * const *mounts;
  22. char path[PATH_MAX + 1];
  23. bool found;
  24. long magic;
  25. };
  26. enum {
  27. FS__SYSFS = 0,
  28. FS__PROCFS = 1,
  29. };
  30. static struct fs fs__entries[] = {
  31. [FS__SYSFS] = {
  32. .name = "sysfs",
  33. .mounts = sysfs__fs_known_mountpoints,
  34. .magic = SYSFS_MAGIC,
  35. },
  36. [FS__PROCFS] = {
  37. .name = "proc",
  38. .mounts = procfs__known_mountpoints,
  39. .magic = PROC_SUPER_MAGIC,
  40. },
  41. };
  42. static bool fs__read_mounts(struct fs *fs)
  43. {
  44. bool found = false;
  45. char type[100];
  46. FILE *fp;
  47. fp = fopen("/proc/mounts", "r");
  48. if (fp == NULL)
  49. return NULL;
  50. while (!found &&
  51. fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
  52. fs->path, type) == 2) {
  53. if (strcmp(type, fs->name) == 0)
  54. found = true;
  55. }
  56. fclose(fp);
  57. return fs->found = found;
  58. }
  59. static int fs__valid_mount(const char *fs, long magic)
  60. {
  61. struct statfs st_fs;
  62. if (statfs(fs, &st_fs) < 0)
  63. return -ENOENT;
  64. else if (st_fs.f_type != magic)
  65. return -ENOENT;
  66. return 0;
  67. }
  68. static bool fs__check_mounts(struct fs *fs)
  69. {
  70. const char * const *ptr;
  71. ptr = fs->mounts;
  72. while (*ptr) {
  73. if (fs__valid_mount(*ptr, fs->magic) == 0) {
  74. fs->found = true;
  75. strcpy(fs->path, *ptr);
  76. return true;
  77. }
  78. ptr++;
  79. }
  80. return false;
  81. }
  82. static void mem_toupper(char *f, size_t len)
  83. {
  84. while (len) {
  85. *f = toupper(*f);
  86. f++;
  87. len--;
  88. }
  89. }
  90. /*
  91. * Check for "NAME_PATH" environment variable to override fs location (for
  92. * testing). This matches the recommendation in Documentation/sysfs-rules.txt
  93. * for SYSFS_PATH.
  94. */
  95. static bool fs__env_override(struct fs *fs)
  96. {
  97. char *override_path;
  98. size_t name_len = strlen(fs->name);
  99. /* name + "_PATH" + '\0' */
  100. char upper_name[name_len + 5 + 1];
  101. memcpy(upper_name, fs->name, name_len);
  102. mem_toupper(upper_name, name_len);
  103. strcpy(&upper_name[name_len], "_PATH");
  104. override_path = getenv(upper_name);
  105. if (!override_path)
  106. return false;
  107. fs->found = true;
  108. strncpy(fs->path, override_path, sizeof(fs->path));
  109. return true;
  110. }
  111. static const char *fs__get_mountpoint(struct fs *fs)
  112. {
  113. if (fs__env_override(fs))
  114. return fs->path;
  115. if (fs__check_mounts(fs))
  116. return fs->path;
  117. if (fs__read_mounts(fs))
  118. return fs->path;
  119. return NULL;
  120. }
  121. static const char *fs__mountpoint(int idx)
  122. {
  123. struct fs *fs = &fs__entries[idx];
  124. if (fs->found)
  125. return (const char *)fs->path;
  126. return fs__get_mountpoint(fs);
  127. }
  128. #define FS__MOUNTPOINT(name, idx) \
  129. const char *name##__mountpoint(void) \
  130. { \
  131. return fs__mountpoint(idx); \
  132. }
  133. FS__MOUNTPOINT(sysfs, FS__SYSFS);
  134. FS__MOUNTPOINT(procfs, FS__PROCFS);