xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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
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
56 fuse_version(void)
57 {
58 	return FUSE_VERSION;
59 }
60 
61 
62 struct fuse_context*
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*
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
98 fuse_unmount(const char* mountpoint, struct fuse_chan* ch)
99 {
100 	// nothing to do
101 }
102 
103 
104 struct fuse*
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 
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
158 fuse_destroy(struct fuse* f)
159 {
160 	// TODO: Implement!
161 }
162 
163 
164 int
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
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
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
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
197 fuse_exit(struct fuse* f)
198 {
199 	// TODO: Implement!
200 }
201 
202 
203 int
204 fuse_interrupted(void)
205 {
206 	// TODO: ?
207 	return false;
208 }
209 
210 
211 int
212 fuse_invalidate(struct fuse* f, const char* path)
213 {
214 	return EINVAL;
215 }
216