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