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
20int
21fuse_main_real(int argc, char* argv[], const struct fuse_operations* op,
22	size_t opSize, void* userData)
23{
24printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, opSize,
25userData);
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
55int
56fuse_version(void)
57{
58	return FUSE_VERSION;
59}
60
61
62struct fuse_context*
63fuse_get_context(void)
64{
65	RequestThread* requestThread = RequestThread::GetCurrentThread();
66	return requestThread != NULL
67		? (fuse_context*)requestThread->GetContext()->GetFSData()
68		: NULL;
69}
70
71
72struct fuse_chan*
73fuse_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
97void
98fuse_unmount(const char* mountpoint, struct fuse_chan* ch)
99{
100	// nothing to do
101}
102
103
104struct fuse*
105fuse_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
131struct 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
157void
158fuse_destroy(struct fuse* f)
159{
160	// TODO: Implement!
161}
162
163
164int
165fuse_loop(struct fuse* f)
166{
167	status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
168	return error == B_OK ? 0 : -1;
169}
170
171
172int
173fuse_loop_mt(struct fuse* f)
174{
175	status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
176	return error == B_OK ? 0 : -1;
177}
178
179
180int
181fuse_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
188int
189fuse_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
196void
197fuse_exit(struct fuse* f)
198{
199	// TODO: Implement!
200}
201
202
203int
204fuse_interrupted(void)
205{
206	// TODO: ?
207	return false;
208}
209
210
211int
212fuse_invalidate(struct fuse* f, const char* path)
213{
214	return EINVAL;
215}
216