xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_main.cpp (revision adb0d19d561947362090081e81d90dde59142026)
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 void
132 fuse_destroy(struct fuse* f)
133 {
134 	// TODO: Implement!
135 }
136 
137 
138 int
139 fuse_loop(struct fuse* f)
140 {
141 	status_t error = FUSEFileSystem::GetInstance()->MainLoop(false);
142 	return error == B_OK ? 0 : -1;
143 }
144 
145 
146 int
147 fuse_loop_mt(struct fuse* f)
148 {
149 	status_t error = FUSEFileSystem::GetInstance()->MainLoop(true);
150 	return error == B_OK ? 0 : -1;
151 }
152 
153 
154 void
155 fuse_exit(struct fuse* f)
156 {
157 	// TODO: Implement!
158 }
159 
160 
161 int
162 fuse_interrupted(void)
163 {
164 	// TODO: ?
165 	return false;
166 }
167 
168 
169 int
170 fuse_invalidate(struct fuse* f, const char* path)
171 {
172 	return EINVAL;
173 }
174