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