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