xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 gHasHaikuFuseExtensions = 0;
21 	// This global can be set to 1 by a Haiku-aware FUSE add-on to signal
22 	// that it implements the Haiku-specific functions in struct
23 	// fuse_operations (those which are guarded by HAS_FUSE_HAIKU_EXTENSIONS).
24 
25 int
26 fuse_main_real(int argc, char* argv[], const struct fuse_operations* op,
27 	size_t opSize, void* userData)
28 {
29 printf("fuse_main_real(%d, %p, %p, %ld, %p)\n", argc, argv, op, opSize,
30 userData);
31 	// Note: We use the fuse_*() functions here to initialize and run the
32 	// file system, although some of them are merely dummies.
33 
34 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
35 
36 	int result = 1;
37 
38 	// create the kernel channel
39 	struct fuse_chan* channel = fuse_mount("/dummy", &args);
40 	if (channel != NULL) {
41 		// create the FUSE handle
42 		struct fuse* fuseHandle = fuse_new(channel, &args, op, opSize,
43 			userData);
44 		if (fuseHandle != NULL) {
45 			// run the main loop
46 			result = fuse_loop_mt(fuseHandle);
47 
48 			fuse_destroy(fuseHandle);
49 		}
50 
51 		fuse_unmount("/dummy", channel);
52 	}
53 
54 	fuse_opt_free_args(&args);
55 
56 	return result;
57 }
58 
59 
60 int
61 fuse_version(void)
62 {
63 	return FUSE_VERSION;
64 }
65 
66 
67 struct fuse_context*
68 fuse_get_context(void)
69 {
70 	RequestThread* requestThread = RequestThread::GetCurrentThread();
71 	return requestThread != NULL
72 		? (fuse_context*)requestThread->GetContext()->GetFSData()
73 		: NULL;
74 }
75 
76 
77 struct fuse_chan*
78 fuse_mount(const char* mountpoint, struct fuse_args* args)
79 {
80 	// make sure the stdin/out/err descriptors are open
81 	while (true) {
82 		int fd = open("/dev/null", O_RDONLY);
83 		if (fd < 0) {
84 			ERROR(("fuse_mount(): Failed to open /dev/null: %s\n",
85 				strerror(errno)));
86 			return NULL;
87 		}
88 
89 		if (fd > 2) {
90 			close(fd);
91 			break;
92 		}
93 	}
94 
95 	if (!fuse_parse_mount_config_args(args))
96 		return NULL;
97 
98 	return (fuse_chan*)FUSEFileSystem::GetInstance();
99 }
100 
101 
102 void
103 fuse_unmount(const char* mountpoint, struct fuse_chan* ch)
104 {
105 	// nothing to do
106 }
107 
108 
109 struct fuse*
110 fuse_new(struct fuse_chan* ch, struct fuse_args* args,
111 	const struct fuse_operations *op, size_t opSize, void *userData)
112 {
113 	// parse args
114 	fuse_config config;
115 	memset(&config, 0, sizeof(config));
116 	config.entry_timeout = 1.0;
117 	config.attr_timeout = 1.0;
118 	config.negative_timeout = 0.0;
119 	config.intr_signal = SIGUSR1;
120 
121 	bool success = fuse_parse_lib_config_args(args, &config);
122 
123 	if (!success) {
124 		PRINT(("fuse_new(): failed to parse arguments!\n"));
125 		return NULL;
126 	}
127 
128 	// run the main loop
129 	status_t error = FUSEFileSystem::GetInstance()->FinishInitClientFS(&config,
130 		op, opSize, userData);
131 
132 	return error == B_OK ? (struct fuse*)FUSEFileSystem::GetInstance() : NULL;
133 }
134 
135 
136 void
137 fuse_destroy(struct fuse* f)
138 {
139 	// TODO: Implement!
140 }
141 
142 
143 int
144 fuse_loop(struct fuse* f)
145 {
146 	status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
147 	return error == B_OK ? 0 : -1;
148 }
149 
150 
151 int
152 fuse_loop_mt(struct fuse* f)
153 {
154 	status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
155 	return error == B_OK ? 0 : -1;
156 }
157 
158 
159 void
160 fuse_exit(struct fuse* f)
161 {
162 	// TODO: Implement!
163 }
164 
165 
166 int
167 fuse_interrupted(void)
168 {
169 	// TODO: ?
170 	return false;
171 }
172 
173 
174 int
175 fuse_invalidate(struct fuse* f, const char* path)
176 {
177 	return EINVAL;
178 }
179