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