fs.c 4.5 KB

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