fs.c 2.9 KB
Newer Older
1
/* TODO merge/factor in debugfs.c here */
2

3
#include <ctype.h>
4 5 6
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
7
#include <stdlib.h>
8 9
#include <string.h>
#include <sys/vfs.h>
10

11 12
#include "debugfs.h"
#include "fs.h"
13 14 15 16 17 18

static const char * const sysfs__fs_known_mountpoints[] = {
	"/sys",
	0,
};

J
Jiri Olsa 已提交
19 20 21 22 23
static const char * const procfs__known_mountpoints[] = {
	"/proc",
	0,
};

24 25 26 27 28 29 30 31 32
struct fs {
	const char		*name;
	const char * const	*mounts;
	char			 path[PATH_MAX + 1];
	bool			 found;
	long			 magic;
};

enum {
J
Jiri Olsa 已提交
33 34
	FS__SYSFS  = 0,
	FS__PROCFS = 1,
35 36 37 38 39 40 41 42
};

static struct fs fs__entries[] = {
	[FS__SYSFS] = {
		.name	= "sysfs",
		.mounts	= sysfs__fs_known_mountpoints,
		.magic	= SYSFS_MAGIC,
	},
J
Jiri Olsa 已提交
43 44 45 46 47
	[FS__PROCFS] = {
		.name	= "proc",
		.mounts	= procfs__known_mountpoints,
		.magic	= PROC_SUPER_MAGIC,
	},
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
};

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;
}

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
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;
}

134 135
static const char *fs__get_mountpoint(struct fs *fs)
{
136 137 138
	if (fs__env_override(fs))
		return fs->path;

139 140 141
	if (fs__check_mounts(fs))
		return fs->path;

142 143 144 145
	if (fs__read_mounts(fs))
		return fs->path;

	return NULL;
146 147
}

148
static const char *fs__mountpoint(int idx)
149 150 151 152 153 154 155 156 157
{
	struct fs *fs = &fs__entries[idx];

	if (fs->found)
		return (const char *)fs->path;

	return fs__get_mountpoint(fs);
}

158 159 160 161
#define FS__MOUNTPOINT(name, idx)	\
const char *name##__mountpoint(void)	\
{					\
	return fs__mountpoint(idx);	\
162 163
}

J
Jiri Olsa 已提交
164 165
FS__MOUNTPOINT(sysfs,  FS__SYSFS);
FS__MOUNTPOINT(procfs, FS__PROCFS);