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