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
|
#define DEBUG
#define ETCFS_MAGIC 0x49c643f4 /* random number */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/dcache.h>
#include <linux/mnt_idmapping.h>
#if 0
static const struct super_operations etcfs_ops = {
};
#endif
static struct dentry *etcfs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags) {
return dentry->d_parent;
}
static const struct inode_operations etcfs_dir_inode_operations = {
.lookup = etcfs_lookup,
};
static int etcfs_readdir(struct file *file, struct dir_context *ctx) {
if (!dir_emit_dots(file, ctx))
return 0;
if (!dir_emit(ctx, "a", 1, 2, 0))
return 0;
return 0;
}
static struct file_operations etcfs_dir_file_ops = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.iterate_shared = etcfs_readdir,
};
static int etcfs_fill_super(struct super_block *sb, struct fs_context *fs) {
struct inode *inode;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = ETCFS_MAGIC;
sb->s_time_gran = 1; /* I have no idea what is's doing */
inode = new_inode(sb);
if (!inode)
return -ENOMEM;
inode->i_ino = get_next_ino();
inode_init_owner(&nop_mnt_idmap, inode, NULL, S_IFDIR);
inode->i_mapping->a_ops = &ram_aops;
/*
mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
mapping_set_unevictable(inode->i_mapping);
*/
simple_inode_init_ts(inode);
/* inode->i_op = &simple_dir_inode_operations; */
inode->i_op = &etcfs_dir_inode_operations;
inode->i_fop = &etcfs_dir_file_ops;
sb->s_root = d_make_root(inode);
if (!sb->s_root)
return -ENOMEM;
return 0;
}
static int etcfs_get_tree(struct fs_context *fc) {
pr_debug("Get tree\n");
return get_tree_nodev(fc, etcfs_fill_super);
}
static struct fs_context_operations etcfs_context_ops = {
.get_tree = etcfs_get_tree,
};
static int etcfs_init_fs_context(struct fs_context *fc) {
pr_debug("Etcfs init fs context\n");
fc->ops = &etcfs_context_ops;
return 0;
}
static struct file_system_type etcfs_fs_type = {
.owner = THIS_MODULE,
.name = "etcfs",
.fs_flags = FS_USERNS_MOUNT,
.init_fs_context = etcfs_init_fs_context,
};
static int __init etcfs_init(void) {
int err;
err = register_filesystem(&etcfs_fs_type);
if (err) {
return err;
}
return 0;
}
static void __exit etcfs_exit(void) {
int err;
err = unregister_filesystem(&etcfs_fs_type);
if (err) {
pr_err("Error, can't unregister filesystem: %d\n", err);
return;
}
return;
}
module_init(etcfs_init);
module_exit(etcfs_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("c4llv07e <igor@c4llv07e.xyz>");
MODULE_DESCRIPTION("Read-only preconfigured etc filesystem");
|