fs.c 3.6 KB

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