1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <string.h>
10
11 #include "Debug.h"
12
13 #include "fuse_api.h"
14 #include "fuse_config.h"
15 #include "FUSEFileSystem.h"
16
17 #include "../RequestThread.h"
18
19
20 int
fuse_main_real(int argc,char * argv[],const struct fuse_operations * op,size_t opSize,void * userData)21 fuse_main_real(int argc, char* argv[], const struct fuse_operations* op,
22 size_t opSize, void* userData)
23 {
24 printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, opSize,
25 userData);
26 // Note: We use the fuse_*() functions here to initialize and run the
27 // file system, although some of them are merely dummies.
28
29 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
30
31 int result = 1;
32
33 // create the kernel channel
34 struct fuse_chan* channel = fuse_mount("/dummy", &args);
35 if (channel != NULL) {
36 // create the FUSE handle
37 struct fuse* fuseHandle = fuse_new(channel, &args, op, opSize,
38 userData);
39 if (fuseHandle != NULL) {
40 // run the main loop
41 result = fuse_loop_mt(fuseHandle);
42
43 fuse_destroy(fuseHandle);
44 }
45
46 fuse_unmount("/dummy", channel);
47 }
48
49 fuse_opt_free_args(&args);
50
51 return result;
52 }
53
54
55 int
fuse_version(void)56 fuse_version(void)
57 {
58 return FUSE_VERSION;
59 }
60
61
62 struct fuse_context*
fuse_get_context(void)63 fuse_get_context(void)
64 {
65 RequestThread* requestThread = RequestThread::GetCurrentThread();
66 return requestThread != NULL
67 ? (fuse_context*)requestThread->GetContext()->GetFSData()
68 : NULL;
69 }
70
71
72 struct fuse_chan*
fuse_mount(const char * mountpoint,struct fuse_args * args)73 fuse_mount(const char* mountpoint, struct fuse_args* args)
74 {
75 // make sure the stdin/out/err descriptors are open
76 while (true) {
77 int fd = open("/dev/null", O_RDONLY);
78 if (fd < 0) {
79 ERROR(("fuse_mount(): Failed to open /dev/null: %s\n",
80 strerror(errno)));
81 return NULL;
82 }
83
84 if (fd > 2) {
85 close(fd);
86 break;
87 }
88 }
89
90 if (!fuse_parse_mount_config_args(args))
91 return NULL;
92
93 return (fuse_chan*)FUSEFileSystem::GetInstance();
94 }
95
96
97 void
fuse_unmount(const char * mountpoint,struct fuse_chan * ch)98 fuse_unmount(const char* mountpoint, struct fuse_chan* ch)
99 {
100 // nothing to do
101 }
102
103
104 struct fuse*
fuse_new(struct fuse_chan * ch,struct fuse_args * args,const struct fuse_operations * op,size_t opSize,void * userData)105 fuse_new(struct fuse_chan* ch, struct fuse_args* args,
106 const struct fuse_operations *op, size_t opSize, void *userData)
107 {
108 // parse args
109 fuse_config config;
110 memset(&config, 0, sizeof(config));
111 config.entry_timeout = 1.0;
112 config.attr_timeout = 1.0;
113 config.negative_timeout = 0.0;
114 config.intr_signal = SIGUSR1;
115
116 bool success = fuse_parse_lib_config_args(args, &config);
117
118 if (!success) {
119 PRINT(("fuse_new(): failed to parse arguments!\n"));
120 return NULL;
121 }
122
123 // run the main loop
124 status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
125 op, opSize, userData);
126
127 return error == B_OK ? (struct fuse*)FUSEFileSystem::GetInstance() : NULL;
128 }
129
130
fuse_lowlevel_new(struct fuse_args * args,const struct fuse_lowlevel_ops * lowLevelOps,size_t lowLevelOpSize,void * userData)131 struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
132 const struct fuse_lowlevel_ops *lowLevelOps, size_t lowLevelOpSize, void *userData)
133 {
134 // parse args
135 fuse_config config;
136 memset(&config, 0, sizeof(config));
137 config.entry_timeout = 1.0;
138 config.attr_timeout = 1.0;
139 config.negative_timeout = 0.0;
140 config.intr_signal = SIGUSR1;
141
142 bool success = fuse_parse_lib_config_args(args, &config);
143
144 if (!success) {
145 PRINT(("fuse_lowlevel_new(): failed to parse arguments!\n"));
146 return NULL;
147 }
148
149 // run the main loop
150 status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
151 lowLevelOps, lowLevelOpSize, userData);
152
153 return error == B_OK ? (struct fuse_session*)FUSEFileSystem::GetInstance() : NULL;
154 }
155
156
157 void
fuse_destroy(struct fuse * f)158 fuse_destroy(struct fuse* f)
159 {
160 // TODO: Implement!
161 }
162
163
164 int
fuse_loop(struct fuse * f)165 fuse_loop(struct fuse* f)
166 {
167 status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
168 return error == B_OK ? 0 : -1;
169 }
170
171
172 int
fuse_loop_mt(struct fuse * f)173 fuse_loop_mt(struct fuse* f)
174 {
175 status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
176 return error == B_OK ? 0 : -1;
177 }
178
179
180 int
fuse_session_loop(struct fuse_session * f)181 fuse_session_loop(struct fuse_session* f)
182 {
183 status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
184 return error == B_OK ? 0 : -1;
185 }
186
187
188 int
fuse_session_loop_mt(struct fuse_session * f)189 fuse_session_loop_mt(struct fuse_session* f)
190 {
191 status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
192 return error == B_OK ? 0 : -1;
193 }
194
195
196 void
fuse_exit(struct fuse * f)197 fuse_exit(struct fuse* f)
198 {
199 // TODO: Implement!
200 }
201
202
203 int
fuse_interrupted(void)204 fuse_interrupted(void)
205 {
206 // TODO: ?
207 return false;
208 }
209
210
211 int
fuse_invalidate(struct fuse * f,const char * path)212 fuse_invalidate(struct fuse* f, const char* path)
213 {
214 return EINVAL;
215 }
216