public FileSystemHandler(FileSystem filesystem, String[] args, OperationsFlags specifiedFlags = None)
        {
            _filesystem = filesystem;

            var flags = specifiedFlags;

            if (flags == None)
            {
                flags = OperationsFlagsFactory.GetOperationsFlags(filesystem.GetType());
                flags = flags | Init;
            }
            InitOperations(flags);
            _opPtr = Operations.Allocate(_operations);

            _argsCount = args.Length;
            _argsPtr   = Arguments.Allocate(args);

            _mountPoint = args[_argsCount - 1];
        }
        public static OperationsFlags GetOperationsFlags(Type type)
        {
            var             methodNames = new HashSet <string>(type.GetMethods(DeclaredOnly | Public | Instance).Select(mi => mi.Name));
            OperationsFlags flags       = None;

            if (methodNames.Contains("OnGetPathStatus"))
            {
                flags |= GetPathStatus;
            }
            if (methodNames.Contains("OnReadSymbolicLink"))
            {
                flags |= ReadSymbolicLink;
            }
            if (methodNames.Contains("OnCreateSpecialFile"))
            {
                flags |= CreateSpecialFile;
            }
            if (methodNames.Contains("OnCreateDirectory"))
            {
                flags |= CreateDirectory;
            }
            if (methodNames.Contains("OnRemoveFile"))
            {
                flags |= RemoveFile;
            }
            if (methodNames.Contains("OnRemoveDirectory"))
            {
                flags |= RemoveDirectory;
            }
            if (methodNames.Contains("OnCreateSymbolicLink"))
            {
                flags |= CreateSymbolicLink;
            }
            if (methodNames.Contains("OnRenamePath"))
            {
                flags |= RenamePath;
            }
            if (methodNames.Contains("OnCreateHardLink"))
            {
                flags |= CreateHardLink;
            }
            if (methodNames.Contains("OnChangePathPermissions"))
            {
                flags |= ChangePathPermissions;
            }
            if (methodNames.Contains("OnChangePathOwner"))
            {
                flags |= ChangePathOwner;
            }
            if (methodNames.Contains("OnTruncateFile"))
            {
                flags |= TruncateFile;
            }
            if (methodNames.Contains("OnChangePathTimes"))
            {
                flags |= ChangePathTimes;
            }
            if (methodNames.Contains("OnOpenHandle"))
            {
                flags |= OpenHandle;
            }
            if (methodNames.Contains("OnReadHandle"))
            {
                flags |= ReadHandle;
            }
            if (methodNames.Contains("OnWriteHandle"))
            {
                flags |= WriteHandle;
            }
            if (methodNames.Contains("OnGetFileSystemStatus"))
            {
                flags |= GetFileSystemStatus;
            }
            if (methodNames.Contains("OnFlushHandle"))
            {
                flags |= FlushHandle;
            }
            if (methodNames.Contains("OnReleaseHandle"))
            {
                flags |= ReleaseHandle;
            }
            if (methodNames.Contains("OnSynchronizeHandle"))
            {
                flags |= SynchronizeHandle;
            }
            if (methodNames.Contains("OnSetPathExtendedAttribute"))
            {
                flags |= SetPathExtendedAttribute;
            }
            if (methodNames.Contains("OnGetPathExtendedAttribute"))
            {
                flags |= GetPathExtendedAttribute;
            }
            if (methodNames.Contains("OnListPathExtendedAttributes"))
            {
                flags |= ListPathExtendedAttributes;
            }
            if (methodNames.Contains("OnRemovePathExtendedAttribute"))
            {
                flags |= RemovePathExtendedAttribute;
            }
            if (methodNames.Contains("OnOpenDirectory"))
            {
                flags |= OpenDirectory;
            }
            if (methodNames.Contains("OnReadDirectory"))
            {
                flags |= ReadDirectory;
            }
            if (methodNames.Contains("OnReleaseDirectory"))
            {
                flags |= ReleaseDirectory;
            }
            if (methodNames.Contains("OnSynchronizeDirectory"))
            {
                flags |= SynchronizeDirectory;
            }
            if (methodNames.Contains("OnInit"))
            {
                flags |= Init;
            }
            if (methodNames.Contains("OnDestroy"))
            {
                flags |= Destroy;
            }
            if (methodNames.Contains("OnAccessPath"))
            {
                flags |= AccessPath;
            }
            if (methodNames.Contains("OnCreateHandle"))
            {
                flags |= CreateHandle;
            }
            if (methodNames.Contains("OnTruncateHandle"))
            {
                flags |= TruncateHandle;
            }
            if (methodNames.Contains("OnGetHandleStatus"))
            {
                flags |= GetHandleStatus;
            }
            if (methodNames.Contains("OnLockHandle"))
            {
                flags |= LockHandle;
            }
            if (methodNames.Contains("OnMapPathLogicalToPhysicalIndex"))
            {
                flags |= MapPathLogicalToPhysicalIndex;
            }

            return(flags);
        }
 private void InitOperations(OperationsFlags opsFlags)
 {
     _operations = new Operations();
     {
         if ((opsFlags & GetPathStatus) != 0)
         {
             _operations.getattr = _OnGetPathStatus;
         }
         else
         {
             _operations.getattr = null;
         }
         if ((opsFlags & ReadSymbolicLink) != 0)
         {
             _operations.readlink = _OnReadSymbolicLink;
         }
         else
         {
             _operations.readlink = null;
         }
         if ((opsFlags & CreateSpecialFile) != 0)
         {
             _operations.mknod = _OnCreateSpecialFile;
         }
         else
         {
             _operations.mknod = null;
         }
         if ((opsFlags & CreateDirectory) != 0)
         {
             _operations.mkdir = _OnCreateDirectory;
         }
         else
         {
             _operations.mkdir = null;
         }
         if ((opsFlags & RemoveFile) != 0)
         {
             _operations.unlink = _OnRemoveFile;
         }
         else
         {
             _operations.unlink = null;
         }
         if ((opsFlags & RemoveDirectory) != 0)
         {
             _operations.rmdir = _OnRemoveDirectory;
         }
         else
         {
             _operations.rmdir = null;
         }
         if ((opsFlags & CreateSymbolicLink) != 0)
         {
             _operations.symlink = _OnCreateSymbolicLink;
         }
         else
         {
             _operations.symlink = null;
         }
         if ((opsFlags & RenamePath) != 0)
         {
             _operations.rename = _OnRenamePath;
         }
         else
         {
             _operations.rename = null;
         }
         if ((opsFlags & CreateHardLink) != 0)
         {
             _operations.link = _OnCreateHardLink;
         }
         else
         {
             _operations.link = null;
         }
         if ((opsFlags & ChangePathPermissions) != 0)
         {
             _operations.chmod = _OnChangePathPermissions;
         }
         else
         {
             _operations.chmod = null;
         }
         if ((opsFlags & ChangePathOwner) != 0)
         {
             _operations.chown = _OnChangePathOwner;
         }
         else
         {
             _operations.chown = null;
         }
         if ((opsFlags & TruncateFile) != 0)
         {
             _operations.truncate = _OnTruncateFile;
         }
         else
         {
             _operations.truncate = null;
         }
         if ((opsFlags & ChangePathTimes) != 0)
         {
             _operations.utime = _OnChangePathTimes;
         }
         else
         {
             _operations.utime = null;
         }
         if ((opsFlags & OpenHandle) != 0)
         {
             _operations.open = _OnOpenHandle;
         }
         else
         {
             _operations.open = null;
         }
         if ((opsFlags & ReadHandle) != 0)
         {
             _operations.read = _OnReadHandle;
         }
         else
         {
             _operations.read = null;
         }
         if ((opsFlags & WriteHandle) != 0)
         {
             _operations.write = _OnWriteHandle;
         }
         else
         {
             _operations.write = null;
         }
         if ((opsFlags & GetFileSystemStatus) != 0)
         {
             _operations.statfs = _OnGetFileSystemStatus;
         }
         else
         {
             _operations.statfs = null;
         }
         if ((opsFlags & FlushHandle) != 0)
         {
             _operations.flush = _OnFlushHandle;
         }
         else
         {
             _operations.flush = null;
         }
         if ((opsFlags & ReleaseHandle) != 0)
         {
             _operations.release = _OnReleaseHandle;
         }
         else
         {
             _operations.release = null;
         }
         if ((opsFlags & SynchronizeHandle) != 0)
         {
             _operations.fsync = _OnSynchronizeHandle;
         }
         else
         {
             _operations.fsync = null;
         }
         if ((opsFlags & SetPathExtendedAttribute) != 0)
         {
             _operations.setxattr = _OnSetPathExtendedAttribute;
         }
         else
         {
             _operations.setxattr = null;
         }
         if ((opsFlags & GetPathExtendedAttribute) != 0)
         {
             _operations.getxattr = _OnGetPathExtendedAttribute;
         }
         else
         {
             _operations.getxattr = null;
         }
         if ((opsFlags & ListPathExtendedAttributes) != 0)
         {
             _operations.listxattr = _OnListPathExtendedAttributes;
         }
         else
         {
             _operations.listxattr = null;
         }
         if ((opsFlags & RemovePathExtendedAttribute) != 0)
         {
             _operations.removexattr = _OnRemovePathExtendedAttribute;
         }
         else
         {
             _operations.removexattr = null;
         }
         if ((opsFlags & OpenDirectory) != 0)
         {
             _operations.opendir = _OnOpenDirectory;
         }
         else
         {
             _operations.opendir = null;
         }
         if ((opsFlags & ReadDirectory) != 0)
         {
             _operations.readdir = _OnReadDirectory;
         }
         else
         {
             _operations.readdir = null;
         }
         if ((opsFlags & ReleaseDirectory) != 0)
         {
             _operations.releasedir = _OnReleaseDirectory;
         }
         else
         {
             _operations.releasedir = null;
         }
         if ((opsFlags & SynchronizeDirectory) != 0)
         {
             _operations.fsyncdir = _OnSynchronizeDirectory;
         }
         else
         {
             _operations.fsyncdir = null;
         }
         if ((opsFlags & Init) != 0)
         {
             _operations.init = _OnInit;
         }
         else
         {
             _operations.init = null;
         }
         if ((opsFlags & Destroy) != 0)
         {
             _operations.destroy = _OnDestroy;
         }
         else
         {
             _operations.destroy = null;
         }
         if ((opsFlags & AccessPath) != 0)
         {
             _operations.access = _OnAccessPath;
         }
         else
         {
             _operations.access = null;
         }
         if ((opsFlags & CreateHandle) != 0)
         {
             _operations.create = _OnCreateHandle;
         }
         else
         {
             _operations.create = null;
         }
         if ((opsFlags & TruncateHandle) != 0)
         {
             _operations.ftruncate = _OnTruncateHandle;
         }
         else
         {
             _operations.ftruncate = null;
         }
         if ((opsFlags & GetHandleStatus) != 0)
         {
             _operations.fgetattr = _OnGetHandleStatus;
         }
         else
         {
             _operations.fgetattr = null;
         }
         if ((opsFlags & LockHandle) != 0)
         {
             _operations.@lock = _OnLockHandle;
         }
         else
         {
             _operations.@lock = null;
         }
         if ((opsFlags & MapPathLogicalToPhysicalIndex) != 0)
         {
             _operations.bmap = _OnMapPathLogicalToPhysicalIndex;
         }
         else
         {
             _operations.bmap = null;
         }
     };
 }