fs.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include <ctype.h>
  2. #include <errno.h>
  3. #include <stdbool.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/vfs.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include "debugfs.h"
  13. #include "fs.h"
  14. #define _STR(x) #x
  15. #define STR(x) _STR(x)
  16. #ifndef SYSFS_MAGIC
  17. #define SYSFS_MAGIC 0x62656572
  18. #endif
  19. #ifndef PROC_SUPER_MAGIC
  20. #define PROC_SUPER_MAGIC 0x9fa0
  21. #endif
  22. #ifndef DEBUGFS_MAGIC
  23. #define DEBUGFS_MAGIC 0x64626720
  24. #endif
  25. static const char * const sysfs__fs_known_mountpoints[] = {
  26. "/sys",
  27. 0,
  28. };
  29. static const char * const procfs__known_mountpoints[] = {
  30. "/proc",
  31. 0,
  32. };
  33. #ifndef DEBUGFS_DEFAULT_PATH
  34. #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
  35. #endif
  36. static const char * const debugfs__known_mountpoints[] = {
  37. DEBUGFS_DEFAULT_PATH,
  38. "/debug",
  39. 0,
  40. };
  41. struct fs {
  42. const char *name;
  43. const char * const *mounts;
  44. char path[PATH_MAX + 1];
  45. bool found;
  46. long magic;
  47. };
  48. enum {
  49. FS__SYSFS = 0,
  50. FS__PROCFS = 1,
  51. FS__DEBUGFS = 2,
  52. };
  53. static struct fs fs__entries[] = {
  54. [FS__SYSFS] = {
  55. .name = "sysfs",
  56. .mounts = sysfs__fs_known_mountpoints,
  57. .magic = SYSFS_MAGIC,
  58. },
  59. [FS__PROCFS] = {
  60. .name = "proc",
  61. .mounts = procfs__known_mountpoints,
  62. .magic = PROC_SUPER_MAGIC,
  63. },
  64. [FS__DEBUGFS] = {
  65. .name = "debugfs",
  66. .mounts = debugfs__known_mountpoints,
  67. .magic = DEBUGFS_MAGIC,
  68. },
  69. };
  70. static bool fs__read_mounts(struct fs *fs)
  71. {
  72. bool found = false;
  73. char type[100];
  74. FILE *fp;
  75. fp = fopen("/proc/mounts", "r");
  76. if (fp == NULL)
  77. return NULL;
  78. while (!found &&
  79. fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
  80. fs->path, type) == 2) {
  81. if (strcmp(type, fs->name) == 0)
  82. found = true;
  83. }
  84. fclose(fp);
  85. return fs->found = found;
  86. }
  87. static int fs__valid_mount(const char *fs, long magic)
  88. {
  89. struct statfs st_fs;
  90. if (statfs(fs, &st_fs) < 0)
  91. return -ENOENT;
  92. else if ((long)st_fs.f_type != magic)
  93. return -ENOENT;
  94. return 0;
  95. }
  96. static bool fs__check_mounts(struct fs *fs)
  97. {
  98. const char * const *ptr;
  99. ptr = fs->mounts;
  100. while (*ptr) {
  101. if (fs__valid_mount(*ptr, fs->magic) == 0) {
  102. fs->found = true;
  103. strcpy(fs->path, *ptr);
  104. return true;
  105. }
  106. ptr++;
  107. }
  108. return false;
  109. }
  110. static void mem_toupper(char *f, size_t len)
  111. {
  112. while (len) {
  113. *f = toupper(*f);
  114. f++;
  115. len--;
  116. }
  117. }
  118. /*
  119. * Check for "NAME_PATH" environment variable to override fs location (for
  120. * testing). This matches the recommendation in Documentation/sysfs-rules.txt
  121. * for SYSFS_PATH.
  122. */
  123. static bool fs__env_override(struct fs *fs)
  124. {
  125. char *override_path;
  126. size_t name_len = strlen(fs->name);
  127. /* name + "_PATH" + '\0' */
  128. char upper_name[name_len + 5 + 1];
  129. memcpy(upper_name, fs->name, name_len);
  130. mem_toupper(upper_name, name_len);
  131. strcpy(&upper_name[name_len], "_PATH");
  132. override_path = getenv(upper_name);
  133. if (!override_path)
  134. return false;
  135. fs->found = true;
  136. strncpy(fs->path, override_path, sizeof(fs->path));
  137. return true;
  138. }
  139. static const char *fs__get_mountpoint(struct fs *fs)
  140. {
  141. if (fs__env_override(fs))
  142. return fs->path;
  143. if (fs__check_mounts(fs))
  144. return fs->path;
  145. if (fs__read_mounts(fs))
  146. return fs->path;
  147. return NULL;
  148. }
  149. static const char *fs__mountpoint(int idx)
  150. {
  151. struct fs *fs = &fs__entries[idx];
  152. if (fs->found)
  153. return (const char *)fs->path;
  154. return fs__get_mountpoint(fs);
  155. }
  156. #define FS__MOUNTPOINT(name, idx) \
  157. const char *name##__mountpoint(void) \
  158. { \
  159. return fs__mountpoint(idx); \
  160. }
  161. FS__MOUNTPOINT(sysfs, FS__SYSFS);
  162. FS__MOUNTPOINT(procfs, FS__PROCFS);
  163. FS__MOUNTPOINT(debugfs, FS__DEBUGFS);
  164. int filename__read_int(const char *filename, int *value)
  165. {
  166. char line[64];
  167. int fd = open(filename, O_RDONLY), err = -1;
  168. if (fd < 0)
  169. return -1;
  170. if (read(fd, line, sizeof(line)) > 0) {
  171. *value = atoi(line);
  172. err = 0;
  173. }
  174. close(fd);
  175. return err;
  176. }
  177. int sysctl__read_int(const char *sysctl, int *value)
  178. {
  179. char path[PATH_MAX];
  180. const char *procfs = procfs__mountpoint();
  181. if (!procfs)
  182. return -1;
  183. snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl);
  184. return filename__read_int(path, value);
  185. }