Example #1
0
        public unsafe void Mount(string[] argList = null)
        {
            lock (_gate)
            {
                try
                {
                    _fuseLoopTask = Task.Factory.StartNew(() =>
                    {
                        if (!LibFuse.IsAvailable)
                        {
                            throw new FuseException($"libfuse({LibFuse.LibraryName}) is not available on this system.");
                        }

                        fuse_args args;
                        fuse *fuse = null;
                        try
                        {
                            LibFuse.fuse_opt_add_arg(&args, "");  // argv[0]
                            if (argList != null)
                            {
                                foreach (var v in argList)
                                {
                                    LibFuse.fuse_opt_add_arg(&args, v);
                                }
                            }

                            fuse_operations ops;
                            ops.getattr     = Marshal.GetFunctionPointerForDelegate(_getattr);
                            ops.readdir     = Marshal.GetFunctionPointerForDelegate(_readdir);
                            ops.open        = Marshal.GetFunctionPointerForDelegate(_open);
                            ops.read        = Marshal.GetFunctionPointerForDelegate(_read);
                            ops.release     = Marshal.GetFunctionPointerForDelegate(_release);
                            ops.write       = Marshal.GetFunctionPointerForDelegate(_write);
                            ops.unlink      = Marshal.GetFunctionPointerForDelegate(_unlink);
                            ops.truncate    = Marshal.GetFunctionPointerForDelegate(_truncate);
                            ops.rmdir       = Marshal.GetFunctionPointerForDelegate(_rmdir);
                            ops.mkdir       = Marshal.GetFunctionPointerForDelegate(_mkdir);
                            ops.create      = Marshal.GetFunctionPointerForDelegate(_create);
                            ops.chmod       = Marshal.GetFunctionPointerForDelegate(_chmod);
                            ops.link        = Marshal.GetFunctionPointerForDelegate(_link);
                            ops.utimens     = Marshal.GetFunctionPointerForDelegate(_utimens);
                            ops.readlink    = Marshal.GetFunctionPointerForDelegate(_readlink);
                            ops.symlink     = Marshal.GetFunctionPointerForDelegate(_symlink);
                            ops.rename      = Marshal.GetFunctionPointerForDelegate(_rename);
                            ops.chown       = Marshal.GetFunctionPointerForDelegate(_chown);
                            ops.statfs      = Marshal.GetFunctionPointerForDelegate(_statfs);
                            ops.flush       = Marshal.GetFunctionPointerForDelegate(_flush);
                            ops.fsync       = Marshal.GetFunctionPointerForDelegate(_fsync);
                            ops.setxattr    = Marshal.GetFunctionPointerForDelegate(_setxattr);
                            ops.getxattr    = Marshal.GetFunctionPointerForDelegate(_getxattr);
                            ops.listxattr   = Marshal.GetFunctionPointerForDelegate(_listxattr);
                            ops.removexattr = Marshal.GetFunctionPointerForDelegate(_removexattr);
                            ops.opendir     = Marshal.GetFunctionPointerForDelegate(_opendir);
                            ops.releasedir  = Marshal.GetFunctionPointerForDelegate(_releasedir);
                            ops.fsyncdir    = Marshal.GetFunctionPointerForDelegate(_fsyncdir);
                            ops.access      = Marshal.GetFunctionPointerForDelegate(_access);
                            ops.fallocate   = Marshal.GetFunctionPointerForDelegate(_fallocate);
                            ops.init        = Marshal.GetFunctionPointerForDelegate(_init);

                            fuse = LibFuse.fuse_new(&args, &ops, (UIntPtr)sizeof(fuse_operations), null);
                            if (fuse == null)
                            {
                                throw CreateException(nameof(LibFuse.fuse_new), 0);
                            }
                            int rv = LibFuse.fuse_mount(fuse, _mountPoint);
                            if (rv != 0)
                            {
                                throw CreateException(nameof(LibFuse.fuse_mount), rv);
                            }
                            try
                            {
                                bool singleThread = !_fileSystem.SupportsMultiThreading || _mountOptions.SingleThread;
                                if (singleThread)
                                {
                                    rv = LibFuse.fuse_loop(fuse);
                                }
                                else
                                {
                                    rv = LibFuse.fuse_loop_mt(fuse, clone_fd: 0);
                                }
                                if (rv == 0)
                                {
                                    _mountTaskCompletion.TrySetResult(null);
                                }
                                else
                                {
                                    _mountTaskCompletion.TrySetException(CreateException(nameof(LibFuse.fuse_loop), rv));
                                }
                            }
                            catch (Exception e)
                            {
                                _mountTaskCompletion.TrySetException(e);
                            }
                            finally
                            {
                                lock (_gate)
                                {
                                    LibFuse.fuse_unmount(fuse);
                                    if (_mounted)
                                    {
                                        _mounted = false;
                                        _fileSystem.Dispose();
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            _mountTaskCompletion.TrySetException(e);
                        }
                        finally
                        {
                            if (fuse != null)
                            {
                                LibFuse.fuse_destroy(fuse);
                            }
                            LibFuse.fuse_opt_free_args(&args);
                        }
                    }, TaskCreationOptions.LongRunning);

                    _mountTaskCompletion.Task.GetAwaiter().GetResult();
                    _mounted = true;
                }
                finally
                {
                    if (!_mounted)
                    {
                        _fileSystem.Dispose();
                    }
                }
            }
        }