-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathoshfs.c
More file actions
170 lines (154 loc) · 4.58 KB
/
Copy pathoshfs.c
File metadata and controls
170 lines (154 loc) · 4.58 KB
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
166
167
168
169
170
/*
* Copyright © 2018 Zitian Li <ztlizitian@gmail.com>
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details.
*/
#define _OSH_FS_VERSION 2018051000
#define FUSE_USE_VERSION 26
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fuse.h>
#include <sys/mman.h>
struct filenode {
char *filename;
void *content;
struct stat *st;
struct filenode *next;
};
static const size_t size = 4 * 1024 * 1024 * (size_t)1024;
static void *mem[64 * 1024];
static struct filenode *root = NULL;
static struct filenode *get_filenode(const char *name)
{
struct filenode *node = root;
while(node) {
if(strcmp(node->filename, name + 1) != 0)
node = node->next;
else
return node;
}
return NULL;
}
static void create_filenode(const char *filename, const struct stat *st)
{
struct filenode *new = (struct filenode *)malloc(sizeof(struct filenode));
new->filename = (char *)malloc(strlen(filename) + 1);
memcpy(new->filename, filename, strlen(filename) + 1);
new->st = (struct stat *)malloc(sizeof(struct stat));
memcpy(new->st, st, sizeof(struct stat));
new->next = root;
new->content = NULL;
root = new;
}
static void *oshfs_init(struct fuse_conn_info *conn)
{
size_t blocknr = sizeof(mem) / sizeof(mem[0]);
size_t blocksize = size / blocknr;
// Demo 1
for(int i = 0; i < blocknr; i++) {
mem[i] = mmap(NULL, blocksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memset(mem[i], 0, blocksize);
}
for(int i = 0; i < blocknr; i++) {
munmap(mem[i], blocksize);
}
// Demo 2
mem[0] = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
for(int i = 0; i < blocknr; i++) {
mem[i] = (char *)mem[0] + blocksize * i;
memset(mem[i], 0, blocksize);
}
for(int i = 0; i < blocknr; i++) {
munmap(mem[i], blocksize);
}
return NULL;
}
static int oshfs_getattr(const char *path, struct stat *stbuf)
{
int ret = 0;
struct filenode *node = get_filenode(path);
if(strcmp(path, "/") == 0) {
memset(stbuf, 0, sizeof(struct stat));
stbuf->st_mode = S_IFDIR | 0755;
} else if(node) {
memcpy(stbuf, node->st, sizeof(struct stat));
} else {
ret = -ENOENT;
}
return ret;
}
static int oshfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
struct filenode *node = root;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
while(node) {
filler(buf, node->filename, node->st, 0);
node = node->next;
}
return 0;
}
static int oshfs_mknod(const char *path, mode_t mode, dev_t dev)
{
struct stat st;
st.st_mode = S_IFREG | 0644;
st.st_uid = fuse_get_context()->uid;
st.st_gid = fuse_get_context()->gid;
st.st_nlink = 1;
st.st_size = 0;
create_filenode(path + 1, &st);
return 0;
}
static int oshfs_open(const char *path, struct fuse_file_info *fi)
{
return 0;
}
static int oshfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
struct filenode *node = get_filenode(path);
if(offset + size > node->st->st_size)
node->st->st_size = offset + size;
node->content = realloc(node->content, node->st->st_size);
memcpy(node->content + offset, buf, size);
return size;
}
static int oshfs_truncate(const char *path, off_t size)
{
struct filenode *node = get_filenode(path);
node->st->st_size = size;
node->content = realloc(node->content, size);
return 0;
}
static int oshfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
struct filenode *node = get_filenode(path);
int ret = size;
if(offset + size > node->st->st_size)
ret = node->st->st_size - offset;
memcpy(buf, node->content + offset, ret);
return ret;
}
static int oshfs_unlink(const char *path)
{
// Not Implemented
return 0;
}
static const struct fuse_operations op = {
.init = oshfs_init,
.getattr = oshfs_getattr,
.readdir = oshfs_readdir,
.mknod = oshfs_mknod,
.open = oshfs_open,
.write = oshfs_write,
.truncate = oshfs_truncate,
.read = oshfs_read,
.unlink = oshfs_unlink,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &op, NULL);
}