diff --git a/src/main/java/dev/dokan/dokan_java/AbstractDokanFileSystem.java b/src/main/java/dev/dokan/dokan_java/AbstractDokanFileSystem.java index 3dd13df2..6afa1af7 100644 --- a/src/main/java/dev/dokan/dokan_java/AbstractDokanFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/AbstractDokanFileSystem.java @@ -10,7 +10,7 @@ import dev.dokan.dokan_java.constants.dokany.MountOption; import dev.dokan.dokan_java.structure.DokanControl; import dev.dokan.dokan_java.structure.DokanOptions; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.lang.reflect.Method; import java.nio.file.Path; @@ -173,10 +173,10 @@ private boolean isImplemented(String funcName) { * @param sectorSize the sector size * @param UNCName * @param threadCount the number of threads spawned for processing filesystem calls - * @param options an {@link EnumIntegerSet} containing {@link MountOption}s + * @param options an {@link MaskValueSet} containing {@link MountOption}s */ @Override - public final synchronized void mount(Path mountPoint, String volumeName, int volumeSerialnumber, boolean blocking, long timeout, long allocationUnitSize, long sectorSize, String UNCName, short threadCount, EnumIntegerSet options) { + public final synchronized void mount(Path mountPoint, String volumeName, int volumeSerialnumber, boolean blocking, long timeout, long allocationUnitSize, long sectorSize, String UNCName, short threadCount, MaskValueSet options) { this.dokanOptions = new DokanOptions(mountPoint.toString(), threadCount, options, UNCName, timeout, allocationUnitSize, sectorSize); this.mountPoint = mountPoint; this.volumeName = volumeName; @@ -216,7 +216,7 @@ public final synchronized void mount(Path mountPoint, String volumeName, int vol * @param mountPoint * @param mountOptions */ - public void mount(Path mountPoint, EnumIntegerSet mountOptions) { + public void mount(Path mountPoint, MaskValueSet mountOptions) { String uncName = null; short threadCount = 5; long timeout = 3000; diff --git a/src/main/java/dev/dokan/dokan_java/DokanUtils.java b/src/main/java/dev/dokan/dokan_java/DokanUtils.java index 1530320f..48f6eb36 100644 --- a/src/main/java/dev/dokan/dokan_java/DokanUtils.java +++ b/src/main/java/dev/dokan/dokan_java/DokanUtils.java @@ -140,19 +140,19 @@ public static int mapFileGenericAccessToGenericAccess(int fileAccess) { public static int convertCreateDispositionToCreationDispostion(int createDisposition) { switch (createDisposition) { case FILE_CREATE: - return CREATE_NEW.getMask(); + return CREATE_NEW.intValue(); case FILE_OPEN: - return OPEN_EXISTING.getMask(); + return OPEN_EXISTING.intValue(); case FILE_OPEN_IF: - return OPEN_ALWAYS.getMask(); + return OPEN_ALWAYS.intValue(); case FILE_OVERWRITE: - return TRUNCATE_EXISTING.getMask(); + return TRUNCATE_EXISTING.intValue(); case FILE_SUPERSEDE: // The documentation isn't clear on the difference between replacing a file // and truncating it. // For now we just map it to create/truncate case FILE_OVERWRITE_IF: - return CREATE_ALWAYS.getMask(); + return CREATE_ALWAYS.intValue(); default: //TODO: maybe throw an exception return 0; diff --git a/src/main/java/dev/dokan/dokan_java/FileSystemInformation.java b/src/main/java/dev/dokan/dokan_java/FileSystemInformation.java index 3589c895..35d39fa8 100644 --- a/src/main/java/dev/dokan/dokan_java/FileSystemInformation.java +++ b/src/main/java/dev/dokan/dokan_java/FileSystemInformation.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java; import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Supplementary class to bundle information of the filesystem. @@ -14,18 +14,18 @@ public final class FileSystemInformation { private final int maxComponentLength; private final String fileSystemName; - private final EnumIntegerSet fileSystemFeatures; + private final MaskValueSet fileSystemFeatures; /** * Provides default values for maxComponentLength and Filesystem name. * - * @param fileSystemFlags An {@link EnumIntegerSet} of features the file system supports. For possible values, see the {@link FileSystemFlag} enum. + * @param fileSystemFlags An {@link MaskValueSet} of features the file system supports. For possible values, see the {@link FileSystemFlag} enum. */ - public FileSystemInformation(EnumIntegerSet fileSystemFlags) { + public FileSystemInformation(MaskValueSet fileSystemFlags) { this(DEFAULT_MAX_COMPONENT_LENGTH, DEFAULT_FS_NAME, fileSystemFlags); } - public FileSystemInformation(final int maxComponentLength, final String fileSystemName, final EnumIntegerSet fileSystemFeatures) { + public FileSystemInformation(final int maxComponentLength, final String fileSystemName, final MaskValueSet fileSystemFeatures) { this.maxComponentLength = maxComponentLength; this.fileSystemName = fileSystemName; this.fileSystemFeatures = fileSystemFeatures; @@ -39,7 +39,7 @@ public String getFileSystemName() { return this.fileSystemName; } - public EnumIntegerSet getFileSystemFeatures() { + public MaskValueSet getFileSystemFeatures() { return this.fileSystemFeatures; } diff --git a/src/main/java/dev/dokan/dokan_java/Mountable.java b/src/main/java/dev/dokan/dokan_java/Mountable.java index d4c0cde7..24106bbe 100644 --- a/src/main/java/dev/dokan/dokan_java/Mountable.java +++ b/src/main/java/dev/dokan/dokan_java/Mountable.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java; import dev.dokan.dokan_java.constants.dokany.MountOption; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.nio.file.Path; @@ -25,9 +25,9 @@ public interface Mountable extends AutoCloseable { * @param sectorSize the sector size * @param UNCName * @param threadCount the number of threads spawned for processing filesystem calls - * @param options an {@link EnumIntegerSet} containing {@link MountOption}s + * @param options an {@link MaskValueSet} containing {@link MountOption}s */ - void mount(Path mountPoint, String volumeName, int volumeSerialnumber, boolean blocking, long timeout, long allocationUnitSize, long sectorSize, String UNCName, short threadCount, EnumIntegerSet options); + void mount(Path mountPoint, String volumeName, int volumeSerialnumber, boolean blocking, long timeout, long allocationUnitSize, long sectorSize, String UNCName, short threadCount, MaskValueSet options); /** * Unmount this object. diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokany/MountError.java b/src/main/java/dev/dokan/dokan_java/constants/dokany/MountError.java index 4aac7542..041c19ca 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/dokany/MountError.java +++ b/src/main/java/dev/dokan/dokan_java/constants/dokany/MountError.java @@ -1,6 +1,6 @@ package dev.dokan.dokan_java.constants.dokany; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.EnumInteger; /** * Return values of com.dokan.java.NativeMethods#DokanMain(DokanOptions, DokanOperations) @@ -17,20 +17,21 @@ public enum MountError implements EnumInteger { MOUNT_POINT_ERROR(-6, "Mount failed: Mount point is invalid."), VERSION_ERROR(-7, "Mount failed: Requested an incompatible version."); - private final int mask; + private final int intValue; private final String description; public static MountError fromInt(final int value) { return EnumInteger.enumFromInt(value, values()); } - MountError(final int mask, final String description) { - this.mask = mask; + MountError(final int intValue, final String description) { + this.intValue = intValue; this.description = description; } - public int getMask() { - return this.mask; + @Override + public int intValue() { + return this.intValue; } public String getDescription() { diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokany/MountOption.java b/src/main/java/dev/dokan/dokan_java/constants/dokany/MountOption.java index 52b77aaf..b542da59 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/dokany/MountOption.java +++ b/src/main/java/dev/dokan/dokan_java/constants/dokany/MountOption.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java.constants.dokany; -import dev.dokan.dokan_java.constants.EnumInteger; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; +import dev.dokan.dokan_java.masking.MaskValueEnum; import dev.dokan.dokan_java.structure.DokanOptions; /** @@ -9,7 +9,7 @@ * * @see Dokany documentation */ -public enum MountOption implements EnumInteger { +public enum MountOption implements MaskValueEnum { DEBUG_MODE(1, "Enable output debug message."), STD_ERR_OUTPUT(2, "Enable output debug message to stderr."), ALT_STREAM(4, "Use alternate stream."), @@ -20,20 +20,21 @@ public enum MountOption implements EnumInteger { CURRENT_SESSION(128, "Mount the drive on current session only."), FILELOCK_USER_MODE(256, "Enable Lockfile/Unlockfile operations. Otherwise Dokan will take care of it."); - private final int mask; + private final int maskingValue; private final String description; - MountOption(final int i, final String desc) { - this.mask = i; + MountOption(final int maskingValue, final String desc) { + this.maskingValue = maskingValue; this.description = desc; } - public static EnumIntegerSet fromInt(final int value) { - return EnumIntegerSet.enumSetFromInt(value, values()); + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } - public int getMask() { - return this.mask; + @Override + public int intValue() { + return this.maskingValue; } public String getDescription() { diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/AccessMask.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/AccessMask.java index 34a2b993..8e2b58fc 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/AccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/AccessMask.java @@ -1,13 +1,14 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Enumeration of the possible AccesMask options. * For more info see the Microsoft Developer Documentation or the normal documentation. */ -public enum AccessMask implements EnumInteger { +public enum AccessMask implements MaskValueEnum { /** * GENERIC_READ * When used in an Access Request operation: When read access to an object is requested, this bit is translated to a combination of bits. These are most often set in the lower 16 bits of the ACCESS_MASK. (Individual protocol specifications MAY specify a different configuration.) The bits that are set are implementation dependent. During this translation, the GENERIC_READ bit is cleared. The resulting ACCESS_MASK bits are the actual permissions that are checked against the ACE structures in the security descriptor that attached to the object. @@ -97,15 +98,18 @@ public enum AccessMask implements EnumInteger { */ DELETE(WinNT.DELETE); - private int mask; + private int maskingValue; - AccessMask(long mask) { - this.mask = (int) mask; + AccessMask(long maskingValue) { + this.maskingValue = (int) maskingValue; } + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); + } @Override - public int getMask() { - return mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateDisposition.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateDisposition.java index 735a0486..b37a6d4c 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateDisposition.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateDisposition.java @@ -2,7 +2,7 @@ import dev.dokan.dokan_java.DokanNativeMethods; import dev.dokan.dokan_java.DokanOperations; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.EnumInteger; import com.sun.jna.ptr.IntByReference; /** @@ -74,14 +74,18 @@ public enum CreateDisposition implements EnumInteger { FILE_OVERWRITE(CreateDispositions.FILE_OVERWRITE), FILE_OVERWRITE_IF(CreateDispositions.FILE_OVERWRITE_IF); - private final int mask; + private final int intValue; - CreateDisposition(int mask) { - this.mask = mask; + CreateDisposition(int intValue) { + this.intValue = intValue; + } + + public static CreateDisposition fromInt(final int value) { + return EnumInteger.enumFromInt(value, values()); } @Override - public int getMask() { - return mask; + public int intValue() { + return this.intValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateOption.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateOption.java index 8c7f57a8..ae0bad66 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateOption.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreateOption.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; +import dev.dokan.dokan_java.masking.MaskValueEnum; /** * Enum of flags specifying the options to apply when the driver creates or opens the file. @@ -9,7 +9,7 @@ * @see Microsofts documentation of ZwCreateFile * @see Dokany documentation of ZwCreateFile */ -public enum CreateOption implements EnumInteger { +public enum CreateOption implements MaskValueEnum { FILE_DIRECTORY_FILE(CreateOptions.FILE_DIRECTORY_FILE), FILE_WRITE_THROUGH(CreateOptions.FILE_WRITE_THROUGH), FILE_SEQUENTIAL_ONLY(CreateOptions.FILE_SEQUENTIAL_ONLY), @@ -29,19 +29,19 @@ public enum CreateOption implements EnumInteger { FILE_NO_COMPRESSION(CreateOptions.FILE_NO_COMPRESSION), FILE_SESSION_AWARE(CreateOptions.FILE_SESSION_AWARE); - private final int mask; + private final int maskingValue; - CreateOption(final int i) { - mask = i; + CreateOption(final int maskingValue) { + this.maskingValue = maskingValue; } - public static EnumIntegerSet fromInt(final int value) { - return EnumIntegerSet.enumSetFromInt(value, values()); + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } @Override - public int getMask() { - return mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreationDisposition.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreationDisposition.java index dde28411..285986d7 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreationDisposition.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/CreationDisposition.java @@ -1,9 +1,8 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.DokanNativeMethods; -import dev.dokan.dokan_java.constants.EnumInteger; import com.sun.jna.platform.win32.WinNT; -import com.sun.jna.ptr.IntByReference; +import dev.dokan.dokan_java.DokanNativeMethods; +import dev.dokan.dokan_java.masking.EnumInteger; /** * Enum of actions to take on a not-necessarily existing file or device. @@ -64,18 +63,19 @@ public enum CreationDisposition implements EnumInteger { OPEN_ALWAYS(WinNT.OPEN_ALWAYS), TRUNCATE_EXISTING(WinNT.TRUNCATE_EXISTING); - private final int mask; + private final int intValue; - CreationDisposition(final int i) { - mask = i; + CreationDisposition(final int intValue) { + this.intValue = intValue; } public static CreationDisposition fromInt(final int value) { return EnumInteger.enumFromInt(value, values()); } - public int getMask() { - return this.mask; + @Override + public int intValue() { + return this.intValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/DirectoryAccessMask.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/DirectoryAccessMask.java index 6970d9e6..72ad5cda 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/DirectoryAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/DirectoryAccessMask.java @@ -1,25 +1,30 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Additional {@link AccessMask} values specific to directories. * * @see Microsoft documentation of ZwCreateFile, Section Parameters, Parameter {@code DesiredAccess} */ -public enum DirectoryAccessMask implements EnumInteger { +public enum DirectoryAccessMask implements MaskValueEnum { LIST_DIRECTORY(WinNT.FILE_LIST_DIRECTORY), TRAVERSE(WinNT.FILE_TRAVERSE); - private final int mask; + private final int maskingValue; - DirectoryAccessMask(int mask) { - this.mask = mask; - } + DirectoryAccessMask(int maskingValue) { + this.maskingValue = maskingValue; + } - @Override - public int getMask() { - return mask; - } + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); + } + + @Override + public int intValue() { + return this.maskingValue; + } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAccessMask.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAccessMask.java index 439a6cb7..f73a867d 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAccessMask.java @@ -1,14 +1,15 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Additional {@link AccessMask} values specific to files. * * @see Microsoft documentation of ZwCreateFile, Section Parameters, Parameter {@code DesiredAccess} */ -public enum FileAccessMask implements EnumInteger { +public enum FileAccessMask implements MaskValueEnum { READ_DATA(WinNT.FILE_READ_DATA), READ_ATTRIBUTES(WinNT.FILE_READ_ATTRIBUTES), READ_EA(WinNT.FILE_READ_EA), @@ -18,14 +19,18 @@ public enum FileAccessMask implements EnumInteger { APPEND_DATA(WinNT.FILE_APPEND_DATA), EXECUTE(WinNT.FILE_EXECUTE); - private final int mask; + private final int maskingValue; - FileAccessMask(int mask) { - this.mask = mask; + FileAccessMask(int maskingValue) { + this.maskingValue = maskingValue; + } + + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } @Override - public int getMask() { - return mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAttribute.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAttribute.java index 617e35c9..fe10fb01 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAttribute.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileAttribute.java @@ -1,8 +1,10 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; -import dev.dokan.dokan_java.structure.EnumIntegerSet; + import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.masking.MaskValueSet; +import dev.dokan.dokan_java.masking.MaskValueEnum; + /** * File attribute flags. They are metadata values stored by the file system on disk and are used by the system. @@ -10,7 +12,7 @@ * @see Microsoft documentation of file attribute constants * @see Microsoft documentation of CreateFileA function including the list of valid file attributes */ -public enum FileAttribute implements EnumInteger { +public enum FileAttribute implements MaskValueEnum { ARCHIVE(WinNT.FILE_ATTRIBUTE_ARCHIVE), COMPRESSED(WinNT.FILE_ATTRIBUTE_COMPRESSED), DEVICE(WinNT.FILE_ATTRIBUTE_DEVICE), @@ -31,17 +33,18 @@ public enum FileAttribute implements EnumInteger { RECALL_ON_DATA_ACCESS(4194394), RECALL_ON_OPEN(262144); - private final int mask; + private final int maskingValue; - public static EnumIntegerSet fromInt(final int value) { - return EnumIntegerSet.enumSetFromInt(value, values()); + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } - FileAttribute(final int mask) { - this.mask = mask; + FileAttribute(final int maskingValue) { + this.maskingValue = maskingValue; } - public int getMask() { - return this.mask; + @Override + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileSystemFlag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileSystemFlag.java index 1ff27622..9a7f5625 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileSystemFlag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileSystemFlag.java @@ -1,9 +1,9 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.DokanOperations; -import dev.dokan.dokan_java.constants.EnumInteger; -import dev.dokan.dokan_java.structure.EnumIntegerSet; import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.DokanOperations; +import dev.dokan.dokan_java.masking.MaskValueSet; +import dev.dokan.dokan_java.masking.MaskValueEnum; /** * Properties which the implemented filesystem supports. @@ -12,12 +12,12 @@ * Returned in {@link DokanOperations#GetVolumeInformation} to the kernel layer indicating what properties your file system implementation supports. *

* - *

They can be arbitrary combined within an {@link EnumIntegerSet}. However FILE_FILE_COMPRESSION and FILE_VOL_IS_COMPRESSED are mutually exclusive.

+ *

They can be arbitrary combined within an {@link MaskValueSet}. However FILE_FILE_COMPRESSION and FILE_VOL_IS_COMPRESSED are mutually exclusive.

* * @see Microsoft Documentation of function GetVolumeInformation, Parameter {@code lpFileSystemFlags} * @see Listing of possible values */ -public enum FileSystemFlag implements EnumInteger { +public enum FileSystemFlag implements MaskValueEnum { NONE(0), CASE_PRESERVED_NAMES(WinNT.FILE_CASE_PRESERVED_NAMES), CASE_SENSITIVE_SEARCH(WinNT.FILE_CASE_SENSITIVE_SEARCH), @@ -41,17 +41,18 @@ public enum FileSystemFlag implements EnumInteger { VOLUME_IS_COMPRESSED(WinNT.FILE_VOLUME_IS_COMPRESSED), VOLUME_QUOTAS(WinNT.FILE_VOLUME_QUOTAS); - private final int mask; + private final int maskingValue; - public static EnumIntegerSet fromInt(final int value) { - return EnumIntegerSet.enumSetFromInt(value, values()); + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } - FileSystemFlag(final int mask) { - this.mask = mask; + FileSystemFlag(final int maskingValue) { + this.maskingValue = maskingValue; } - public int getMask() { - return this.mask; + @Override + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/NtStatus.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/NtStatus.java index 809b018a..3f96b287 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/NtStatus.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/NtStatus.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.EnumInteger; /** * NTSTATUS values are status codes indicating the success or reason of failure of called methods. @@ -1810,21 +1810,25 @@ public enum NtStatus implements EnumInteger { VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED(0XC03A0018, "The chain of virtual hard disks is corrupted. A differencing disk is indicated in its own parent chain."), VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT(0XC03A0019, "The chain of virtual hard disks is inaccessible. There was an error opening a virtual hard disk further up the chain."); - private final int mask; + private final int intValue; private final String description; - NtStatus(final int mask, final String description) { - this.mask = mask; + NtStatus(final int intValue, final String description) { + this.intValue = intValue; this.description = description; } + public static NtStatus fromInt(final int value) { + return EnumInteger.enumFromInt(value, values()); + } + @Override - public int getMask() { - return mask; + public int intValue() { + return this.intValue; } public String getDescription() { - return description; + return this.description; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/AccessControlEntryFlag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/AccessControlEntryFlag.java index 2ae8614c..6b2cc855 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/AccessControlEntryFlag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/AccessControlEntryFlag.java @@ -1,13 +1,14 @@ package dev.dokan.dokan_java.constants.microsoft.filesecurity; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Enumeration of the different ACE control flags. *

* From the Microsoft documentation: An unsigned 8-bit integer that specifies a set of ACE type-specific control flags. This field can be a combination of the following values. */ -public enum AccessControlEntryFlag implements EnumInteger { +public enum AccessControlEntryFlag implements MaskValueEnum { /** * Child objects that are containers, such as directories, inherit the ACE as an effective ACE. The inherited ACE is inheritable unless the NO_PROPAGATE_INHERIT_ACE bit flag is also set. @@ -53,15 +54,18 @@ public enum AccessControlEntryFlag implements EnumInteger { SUCCESSFUL_ACCESS_ACE_FLAG(0x40); - private final int mask; + private final int maskingValue; - AccessControlEntryFlag(int mask) { - this.mask = mask; + AccessControlEntryFlag(int maskingValue) { + this.maskingValue = maskingValue; } + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); + } @Override - public int getMask() { - return mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/SecurityDescriptorControlFlag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/SecurityDescriptorControlFlag.java index e27a6cb7..30a12183 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/SecurityDescriptorControlFlag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/filesecurity/SecurityDescriptorControlFlag.java @@ -1,12 +1,13 @@ package dev.dokan.dokan_java.constants.microsoft.filesecurity; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; /** * Enumeration of the different control flags that can be set in the header of a security descriptor * The documentation is taken from the official Microsoft doc. */ -public enum SecurityDescriptorControlFlag implements EnumInteger { +public enum SecurityDescriptorControlFlag implements MaskValueEnum { /** * Self-Relative @@ -104,14 +105,17 @@ public enum SecurityDescriptorControlFlag implements EnumInteger { */ OD(1 << 0); - private final int mask; + private final int maskingValue; - SecurityDescriptorControlFlag(int mask) { - this.mask = mask; + SecurityDescriptorControlFlag(int maskingValue) { + this.maskingValue = maskingValue; } + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); + } @Override - public int getMask() { - return mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/examples/DirListingFileSystem.java b/src/main/java/dev/dokan/dokan_java/examples/DirListingFileSystem.java index dc79530a..e3608a80 100644 --- a/src/main/java/dev/dokan/dokan_java/examples/DirListingFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/examples/DirListingFileSystem.java @@ -10,22 +10,19 @@ import dev.dokan.dokan_java.DokanOperations; import dev.dokan.dokan_java.DokanUtils; import dev.dokan.dokan_java.FileSystemInformation; -import dev.dokan.dokan_java.constants.EnumInteger; import dev.dokan.dokan_java.constants.microsoft.CreateDisposition; import dev.dokan.dokan_java.constants.microsoft.CreateOption; -import dev.dokan.dokan_java.constants.microsoft.FileAttribute; import dev.dokan.dokan_java.constants.microsoft.NtStatuses; -import dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes; +import dev.dokan.dokan_java.masking.EnumInteger; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.ByHandleFileInformation; import dev.dokan.dokan_java.structure.DokanFileInfo; import dev.dokan.dokan_java.structure.DokanIOSecurityContext; -import dev.dokan.dokan_java.structure.EnumIntegerSet; import java.io.IOException; import java.nio.file.FileStore; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.DosFileAttributeView; import java.nio.file.attribute.DosFileAttributes; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; @@ -89,7 +86,7 @@ public int zwCreateFile(WString rawPath, DokanIOSecurityContext securityContext, } if (Files.isDirectory(p)) { - if ( EnumIntegerSet.enumSetFromInt(rawCreateOptions, CreateOption.values()).contains(CreateOption.FILE_NON_DIRECTORY_FILE)) { + if (MaskValueSet.maskValueSet(rawCreateOptions, CreateOption.values()).contains(CreateOption.FILE_NON_DIRECTORY_FILE)) { return NtStatuses.STATUS_FILE_IS_A_DIRECTORY; } else { dokanFileInfo.IsDirectory = 1; @@ -198,7 +195,7 @@ public int getVolumeInformation(Pointer rawVolumeNameBuffer, int rawVolumeNameSi rawVolumeNameBuffer.setWideString(0L, DokanUtils.trimStrToSize(this.volumeName, rawVolumeNameSize)); rawVolumeSerialNumber.setValue(this.volumeSerialnumber); rawMaximumComponentLength.setValue(this.fileSystemInformation.getMaxComponentLength()); - rawFileSystemFlags.setValue(this.fileSystemInformation.getFileSystemFeatures().toInt()); + rawFileSystemFlags.setValue(this.fileSystemInformation.getFileSystemFeatures().intValue()); rawFileSystemNameBuffer.setWideString(0L, DokanUtils.trimStrToSize(this.fileSystemInformation.getFileSystemName(), rawFileSystemNameSize)); return NtStatuses.STATUS_SUCCESS; } diff --git a/src/main/java/dev/dokan/dokan_java/constants/EnumInteger.java b/src/main/java/dev/dokan/dokan_java/masking/EnumInteger.java similarity index 62% rename from src/main/java/dev/dokan/dokan_java/constants/EnumInteger.java rename to src/main/java/dev/dokan/dokan_java/masking/EnumInteger.java index bb61c966..d1464329 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/EnumInteger.java +++ b/src/main/java/dev/dokan/dokan_java/masking/EnumInteger.java @@ -1,9 +1,9 @@ -package dev.dokan.dokan_java.constants; +package dev.dokan.dokan_java.masking; /** - * An EnumInteger is an object that is represented by an 32bit integer value. + * An EnumInteger is an enum that is represented by an 32bit integer value. */ -public interface EnumInteger { +public interface EnumInteger extends IntegerConvertible { /** * Converts an 32bit integer into an object. @@ -17,20 +17,18 @@ public interface EnumInteger { * * @throws IllegalArgumentException if none of the EnumIntegers equals the given value */ - static T enumFromInt(final int value, final T[] enumValues) { + static & EnumInteger> T enumFromInt(final int value, final T[] enumValues) { for (final T current : enumValues) { - if (value == current.getMask()) { + if (value == current.intValue()) { return current; } } + throw new IllegalArgumentException("Invalid int value: " + value); } - /** - * Returns the 32bit integer value which represents this object. - * - * @return the value representing this object. - */ - int getMask(); + static & EnumInteger> T enumFromInt(final int value, final Class type) { + return enumFromInt(value, type.getEnumConstants()); + } } diff --git a/src/main/java/dev/dokan/dokan_java/masking/IntegerConvertible.java b/src/main/java/dev/dokan/dokan_java/masking/IntegerConvertible.java new file mode 100644 index 00000000..52ca897b --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/masking/IntegerConvertible.java @@ -0,0 +1,15 @@ +package dev.dokan.dokan_java.masking; + +/** + * An IntegerConvertible is an object that is represented by an 32bit integer value. + */ +public interface IntegerConvertible { + + /** + * Returns the 32bit integer value which represents this object. + * + * @return the value representing this object. + */ + int intValue(); + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/masking/MaskValueEnum.java b/src/main/java/dev/dokan/dokan_java/masking/MaskValueEnum.java new file mode 100644 index 00000000..34decc7e --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/masking/MaskValueEnum.java @@ -0,0 +1,9 @@ +package dev.dokan.dokan_java.masking; + + +public interface MaskValueEnum extends EnumInteger { + + default int maskingValue() { + return intValue(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/masking/MaskValueSet.java b/src/main/java/dev/dokan/dokan_java/masking/MaskValueSet.java new file mode 100644 index 00000000..a81ee40f --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/masking/MaskValueSet.java @@ -0,0 +1,54 @@ +package dev.dokan.dokan_java.masking; + +import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; + +import java.util.Set; + +/** + * Used to store multiple {@link MaskValueEnum} values such as {@link FileSystemFlag} and {@link MountOption}. + * + * @param Type of {@link EnumInteger} + */ +public interface MaskValueSet & MaskValueEnum> extends Set, IntegerConvertible { + + static & MaskValueEnum> MaskValueSet emptySet(Class clazz) { + return new MaskValueSetImpl<>(clazz); + } + + @SafeVarargs + static & MaskValueEnum> MaskValueSet of(T first, T... others) { + return new MaskValueSetImpl<>(first, others); + } + + /** + * Creates a set of MaskValueEnums which corresponds to the bit flag given as an 32bit integer. + *

+ * The type of the set is the enum class of the input array + * + * @param intValue the integer value of the combined bitflag + * @param allEnumValues all possible values of this MaskValueEnum + * @param enum type of the array implementing the MaskValueEnum interface + * @return a set of MaskValueEnum values whose mask were set in the intValue + */ + static & MaskValueEnum> MaskValueSet maskValueSet(final int intValue, final T[] allEnumValues) { + MaskValueSet elements = new MaskValueSetImpl<>(allEnumValues[0].getDeclaringClass()); + int remainingValues = intValue; + for (T current : allEnumValues) { + int mask = current.intValue(); + + if ((remainingValues & mask) == mask) { + elements.add(current); + remainingValues -= mask; + } + } + return elements; + } + + static & MaskValueEnum> MaskValueSet maskValueSet(final int intValue, final Class type) { + return maskValueSet(intValue, type.getEnumConstants()); + } + + void add(T... items); + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/masking/MaskValueSetImpl.java b/src/main/java/dev/dokan/dokan_java/masking/MaskValueSetImpl.java new file mode 100644 index 00000000..73937947 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/masking/MaskValueSetImpl.java @@ -0,0 +1,63 @@ +package dev.dokan.dokan_java.masking; + + +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Objects; + + +public class MaskValueSetImpl & MaskValueEnum> extends AbstractSet implements MaskValueSet { + + private final EnumSet elements; + + public MaskValueSetImpl(final Class clazz) { + this.elements = EnumSet.noneOf(clazz); + } + + @SafeVarargs + public MaskValueSetImpl(T first, T... others) { + this.elements = EnumSet.of(first, others); + } + + @SafeVarargs + @Override + public final void add(T... items) { + if (items == null) { + throw new IllegalArgumentException("Adding null is not allowed."); + } + + Arrays.stream(items).filter(Objects::nonNull).forEach(this::add); + } + + @Override + public int intValue() { + int toReturn = 0; + for (final T current : this.elements) { + toReturn |= current.intValue(); + } + return toReturn; + } + + @Override + public boolean add(final T e) { + return this.elements.add(e); + } + + @Override + public Iterator iterator() { + return this.elements.iterator(); + } + + @Override + public int size() { + return this.elements.size(); + } + + @Override + public String toString() { + return "EnumIntegerSet(elements=" + this.elements + ")"; + } + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/structure/ByHandleFileInformation.java b/src/main/java/dev/dokan/dokan_java/structure/ByHandleFileInformation.java index 6d076727..6dc83467 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/ByHandleFileInformation.java +++ b/src/main/java/dev/dokan/dokan_java/structure/ByHandleFileInformation.java @@ -7,6 +7,7 @@ import com.sun.jna.platform.win32.WinBase; import com.sun.jna.platform.win32.WinBase.FILETIME; import com.sun.jna.platform.win32.WinNT; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.nio.file.Path; import java.nio.file.attribute.FileTime; @@ -104,9 +105,9 @@ public ByHandleFileInformation(Path filePath, int attrs, FileTime creationTime, this.dwVolumeSerialNumber = volumeSerialNumber; } - public ByHandleFileInformation(Path filePath, EnumIntegerSet attrs, FileTime creationTime, FileTime lastAccessTime, FileTime lastWriteTime, int volumeSerialNumber, long fileSize, long fileIndex) { + public ByHandleFileInformation(Path filePath, MaskValueSet attrs, FileTime creationTime, FileTime lastAccessTime, FileTime lastWriteTime, int volumeSerialNumber, long fileSize, long fileIndex) { this.filePath = filePath; - this.dwFileAttributes = attrs.toInt(); + this.dwFileAttributes = attrs.intValue(); this.setTimes(creationTime.toMillis(), lastAccessTime.toMillis(), lastWriteTime.toMillis()); this.setIndex(fileIndex); this.setFileSize(fileSize); @@ -135,8 +136,8 @@ public void copyTo(final ByHandleFileInformation infoToReceive) { infoToReceive.dwVolumeSerialNumber = dwVolumeSerialNumber; } - public void setAttributes(final EnumIntegerSet attributes) { - this.dwFileAttributes = attributes != null ? attributes.toInt() : FileAttribute.NORMAL.getMask(); + public void setAttributes(final MaskValueSet attributes) { + this.dwFileAttributes = attributes != null ? attributes.intValue() : FileAttribute.NORMAL.intValue(); } public void setTimes(final long creationTime, final long lastAccessTime, final long lastWriteTime) { diff --git a/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java b/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java index 85bb2415..993ce25d 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java +++ b/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java @@ -5,6 +5,7 @@ import dev.dokan.dokan_java.constants.dokany.MountOption; import com.sun.jna.Structure; import com.sun.jna.WString; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.util.Arrays; import java.util.List; @@ -68,10 +69,10 @@ public DokanOptions() { } - public DokanOptions(final String mountPoint, final short threadCount, final EnumIntegerSet mountOptions, final String uncName, final long timeout, final long allocationUnitSize, final long sectorSize) { + public DokanOptions(final String mountPoint, final short threadCount, final MaskValueSet mountOptions, final String uncName, final long timeout, final long allocationUnitSize, final long sectorSize) { MountPoint = new WString(mountPoint); ThreadCount = threadCount; - Options = mountOptions.toInt(); + Options = mountOptions.intValue(); if (uncName != null) { UNCName = new WString(uncName); } else { @@ -82,8 +83,8 @@ public DokanOptions(final String mountPoint, final short threadCount, final Enum SectorSize = sectorSize; } - public EnumIntegerSet getMountOptions() { - return EnumIntegerSet.enumSetFromInt(this.Options, MountOption.values()); + public MaskValueSet getMountOptions() { + return MaskValueSet.maskValueSet(this.Options, MountOption.values()); } @Override diff --git a/src/main/java/dev/dokan/dokan_java/structure/EnumIntegerSet.java b/src/main/java/dev/dokan/dokan_java/structure/EnumIntegerSet.java deleted file mode 100644 index 76c14849..00000000 --- a/src/main/java/dev/dokan/dokan_java/structure/EnumIntegerSet.java +++ /dev/null @@ -1,95 +0,0 @@ -package dev.dokan.dokan_java.structure; - -import dev.dokan.dokan_java.constants.EnumInteger; -import dev.dokan.dokan_java.constants.dokany.MountOption; -import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; - -import java.util.AbstractSet; -import java.util.EnumSet; -import java.util.Iterator; - -/** - * Used to store multiple {@link EnumInteger} values such as {@link FileSystemFlag} and {@link MountOption}. - * - * @param Type of {@link EnumInteger} - */ -public final class EnumIntegerSet & EnumInteger> extends AbstractSet { - - private final EnumSet elements; - - public EnumIntegerSet(final Class clazz) { - this.elements = EnumSet.noneOf(clazz); - } - - @SafeVarargs - public EnumIntegerSet(T first, T... others) { - this.elements = EnumSet.of(first, others); - } - - /** - * Creates a set of enumIntegers which corresponds to the bit flag given as an 32bit integer. - *

- * The type of the set is the enum class of the input array - * - * @param intValue the integer value of the combined bitflag - * @param allEnumValues all possible values of this enumInteger - * @param enum type of the array implementing the EnumInteger interface - * @return a set of enumInteger values whose mask were active in the intValue - */ - public static & EnumInteger> EnumIntegerSet enumSetFromInt(final int intValue, final T[] allEnumValues) { - EnumIntegerSet elements = new EnumIntegerSet<>(allEnumValues[0].getDeclaringClass()); - int remainingValues = intValue; - for (T current : allEnumValues) { - int mask = current.getMask(); - - if ((remainingValues & mask) == mask) { - elements.add(current); - remainingValues -= mask; - } - } - return elements; - } - - @SafeVarargs - public final void add(T item, T... items) { - if (item == null) { - throw new IllegalArgumentException("Adding null is not allowed."); - } else { - elements.add(item); - for (final T it : items) { - if (it != null) { - elements.add(it); - } - } - } - } - - public int toInt() { - int toReturn = 0; - for (final T current : elements) { - toReturn |= current.getMask(); - } - return toReturn; - } - - @Override - public boolean add(final T e) { - return elements.add(e); - } - - @Override - public Iterator iterator() { - return elements.iterator(); - } - - @Override - public int size() { - return elements.size(); - } - - @Override - public String toString() { - return "EnumIntegerSet(elements=" + this.elements + ")"; - } - -} diff --git a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessAllowedACE.java b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessAllowedACE.java index 23201041..2303a0fe 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessAllowedACE.java +++ b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessAllowedACE.java @@ -1,6 +1,6 @@ package dev.dokan.dokan_java.structure.filesecurity; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.constants.microsoft.AccessMask; import dev.dokan.dokan_java.constants.microsoft.filesecurity.AccessControlEntryFlag; import dev.dokan.dokan_java.constants.microsoft.filesecurity.AccessControlEntryType; @@ -9,11 +9,11 @@ public class AccessAllowedACE extends AccessControlEntry { - EnumIntegerSet rights; + MaskValueSet rights; SecurityIdentifier sid; - public AccessAllowedACE(EnumIntegerSet flags, SecurityIdentifier sid, EnumIntegerSet rights) { + public AccessAllowedACE(MaskValueSet flags, SecurityIdentifier sid, MaskValueSet rights) { super(AccessControlEntryType.ACCESS_ALLOWED_ACE_TYPE, flags); this.rights = rights; this.sid = sid; @@ -23,9 +23,9 @@ public AccessAllowedACE(EnumIntegerSet flags, SecurityId public byte[] toByteArray() { ByteBuffer buf = ByteBuffer.allocate(sizeOfByteArray()); buf.put(type.toByteArray()); - buf.put((byte) flags.toInt()); + buf.put((byte) flags.intValue()); buf.putShort(Short.reverseBytes((short) sizeOfByteArray())); - buf.putInt(Integer.reverseBytes(rights.toInt())); + buf.putInt(Integer.reverseBytes(rights.intValue())); buf.put(sid.toByteArray()); return buf.array(); } diff --git a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessControlEntry.java b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessControlEntry.java index 4cd90ed9..1599d4e0 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessControlEntry.java +++ b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/AccessControlEntry.java @@ -3,15 +3,15 @@ import dev.dokan.dokan_java.Byteable; import dev.dokan.dokan_java.constants.microsoft.filesecurity.AccessControlEntryFlag; import dev.dokan.dokan_java.constants.microsoft.filesecurity.AccessControlEntryType; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; public abstract class AccessControlEntry implements Byteable { protected final AccessControlEntryType type; - protected final EnumIntegerSet flags; + protected final MaskValueSet flags; - protected AccessControlEntry(AccessControlEntryType type, EnumIntegerSet flags) { + protected AccessControlEntry(AccessControlEntryType type, MaskValueSet flags) { this.type = type; this.flags = flags; } diff --git a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptor.java b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptor.java index a4157e4c..86d822c6 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptor.java +++ b/src/main/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptor.java @@ -2,7 +2,7 @@ import dev.dokan.dokan_java.Byteable; import dev.dokan.dokan_java.constants.microsoft.filesecurity.SecurityDescriptorControlFlag; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.nio.ByteBuffer; import java.util.Optional; @@ -42,10 +42,10 @@ public class SelfRelativeSecurityDescriptor implements Byteable { * Control * An unsigned 16-bit field that specifies control access bit flags. The Self Relative (SR) bit MUST be set when the security descriptor is in self-relative format, represented by a EnumIntegerSet of ControlFlags * - * @see EnumIntegerSet + * @see MaskValueSet * @see SecurityDescriptorControlFlag */ - private EnumIntegerSet control; + private MaskValueSet control; /** * OwnerSid @@ -89,7 +89,7 @@ public class SelfRelativeSecurityDescriptor implements Byteable { * * @param control */ - private SelfRelativeSecurityDescriptor(EnumIntegerSet control) { + private SelfRelativeSecurityDescriptor(MaskValueSet control) { this.control = control; this.ownerSid = Optional.empty(); this.groupSid = Optional.empty(); @@ -97,7 +97,7 @@ private SelfRelativeSecurityDescriptor(EnumIntegerSet control, SecurityIdentifier ownerSid, SecurityIdentifier groupSid, AccessControlList sacl, AccessControlList dacl) { + private SelfRelativeSecurityDescriptor(MaskValueSet control, SecurityIdentifier ownerSid, SecurityIdentifier groupSid, AccessControlList sacl, AccessControlList dacl) { this.control = control; if (ownerSid != null) { this.ownerSid = Optional.of(ownerSid); @@ -145,7 +145,7 @@ public byte[] toByteArray() { ByteBuffer buf = ByteBuffer.allocate(sizeOfByteArray()); buf.put(revision); buf.put(sbz1); - buf.putShort(Short.reverseBytes((short) control.toInt())); + buf.putShort(Short.reverseBytes((short) control.intValue())); buf.putInt(Integer.reverseBytes(offsetOwner)); buf.putInt(Integer.reverseBytes(offsetGroup)); buf.putInt(Integer.reverseBytes(offsetSacl)); @@ -168,8 +168,8 @@ public int sizeOfByteArray() { + dacl.map(AccessControlList::sizeOfByteArray).orElse(0); } - public static SelfRelativeSecurityDescriptor createEmptySD(EnumIntegerSet flags) { - if ((flags.toInt() & (SecurityDescriptorControlFlag.DP.getMask() | SecurityDescriptorControlFlag.SP.getMask())) == 0) { + public static SelfRelativeSecurityDescriptor createEmptySD(MaskValueSet flags) { + if ((flags.intValue() & (SecurityDescriptorControlFlag.DP.intValue() | SecurityDescriptorControlFlag.SP.intValue())) == 0) { flags.add(SecurityDescriptorControlFlag.SR); return new SelfRelativeSecurityDescriptor(flags); } else { @@ -178,13 +178,13 @@ public static SelfRelativeSecurityDescriptor createEmptySD(EnumIntegerSet flags, SecurityIdentifier owner, SecurityIdentifier group, AccessControlList sacl, AccessControlList dacl) { - int controlMask = flags.toInt(); - if ((controlMask & SecurityDescriptorControlFlag.DP.getMask()) != 0 && dacl == null) { + public static SelfRelativeSecurityDescriptor createSD(MaskValueSet flags, SecurityIdentifier owner, SecurityIdentifier group, AccessControlList sacl, AccessControlList dacl) { + int controlMask = flags.intValue(); + if ((controlMask & SecurityDescriptorControlFlag.DP.intValue()) != 0 && dacl == null) { //abort return null; } - if ((controlMask & SecurityDescriptorControlFlag.SP.getMask()) != 0 && sacl == null) { + if ((controlMask & SecurityDescriptorControlFlag.SP.intValue()) != 0 && sacl == null) { //abort return null; } diff --git a/src/test/java/dev/dokan/dokan_java/examples/DirListingFSTest.java b/src/test/java/dev/dokan/dokan_java/examples/DirListingFSTest.java index e54c9270..9d97eb76 100644 --- a/src/test/java/dev/dokan/dokan_java/examples/DirListingFSTest.java +++ b/src/test/java/dev/dokan/dokan_java/examples/DirListingFSTest.java @@ -3,7 +3,7 @@ import dev.dokan.dokan_java.FileSystemInformation; import dev.dokan.dokan_java.constants.dokany.MountOption; import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.io.IOException; @@ -17,11 +17,9 @@ public static void main(String[] args) { System.out.println("Starting Dokany MirrorFS"); Path mountPoint = Path.of("M:\\mnt\\"); - EnumIntegerSet mountOptions = new EnumIntegerSet<>(MountOption.class); - mountOptions.add(MountOption.STD_ERR_OUTPUT, MountOption.WRITE_PROTECTION, MountOption.CURRENT_SESSION); + MaskValueSet mountOptions = MaskValueSet.of(MountOption.STD_ERR_OUTPUT, MountOption.WRITE_PROTECTION, MountOption.CURRENT_SESSION); - EnumIntegerSet fsFeatures = new EnumIntegerSet<>(FileSystemFlag.class); - fsFeatures.add(FileSystemFlag.READ_ONLY_VOLUME, FileSystemFlag.CASE_PRESERVED_NAMES); + MaskValueSet fsFeatures = MaskValueSet.of(FileSystemFlag.READ_ONLY_VOLUME, FileSystemFlag.CASE_PRESERVED_NAMES); FileSystemInformation fsInfo = new FileSystemInformation(fsFeatures); try (DirListingFileSystem fs = new DirListingFileSystem(Paths.get("M:\\test"), fsInfo)) { fs.mount(mountPoint, mountOptions); diff --git a/src/test/java/dev/dokan/dokan_java/constants/EnumIntegerTest.java b/src/test/java/dev/dokan/dokan_java/masking/EnumIntegerTest.java similarity index 86% rename from src/test/java/dev/dokan/dokan_java/constants/EnumIntegerTest.java rename to src/test/java/dev/dokan/dokan_java/masking/EnumIntegerTest.java index 3d0996ae..ca414295 100644 --- a/src/test/java/dev/dokan/dokan_java/constants/EnumIntegerTest.java +++ b/src/test/java/dev/dokan/dokan_java/masking/EnumIntegerTest.java @@ -1,4 +1,4 @@ -package dev.dokan.dokan_java.constants; +package dev.dokan.dokan_java.masking; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -8,7 +8,7 @@ public class EnumIntegerTest { @Test void FromIntegerOverEnumToInteger() { int val = 4096; - Assertions.assertEquals(val, EnumInteger.enumFromInt(val, TestEnum.values()).getMask()); + Assertions.assertEquals(val, EnumInteger.enumFromInt(val, TestEnum.values()).intValue()); } @Test @@ -28,7 +28,7 @@ enum TestEnum implements EnumInteger { } @Override - public int getMask() { + public int intValue() { return val; } } diff --git a/src/test/java/dev/dokan/dokan_java/structure/EnumIntegerSetTest.java b/src/test/java/dev/dokan/dokan_java/masking/MaskValueSetTest.java similarity index 58% rename from src/test/java/dev/dokan/dokan_java/structure/EnumIntegerSetTest.java rename to src/test/java/dev/dokan/dokan_java/masking/MaskValueSetTest.java index 646a0aa4..363c9f50 100644 --- a/src/test/java/dev/dokan/dokan_java/structure/EnumIntegerSetTest.java +++ b/src/test/java/dev/dokan/dokan_java/masking/MaskValueSetTest.java @@ -1,23 +1,22 @@ -package dev.dokan.dokan_java.structure; +package dev.dokan.dokan_java.masking; -import dev.dokan.dokan_java.constants.EnumInteger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class EnumIntegerSetTest { +public class MaskValueSetTest { @Test void fromIntOverEnumIntegerSetToInt() { - int val = TestEnum.A.getMask() | TestEnum.B.getMask() | TestEnum.C.getMask(); - EnumIntegerSet testSet = EnumIntegerSet.enumSetFromInt(val, TestEnum.values()); + int val = TestEnum.A.intValue() | TestEnum.B.intValue() | TestEnum.C.intValue(); + MaskValueSet testSet = MaskValueSet.maskValueSet(val, TestEnum.values()); Assertions.assertFalse(testSet.contains(TestEnum.D)); Assertions.assertTrue(testSet.contains(TestEnum.A)); Assertions.assertTrue(testSet.contains(TestEnum.B)); Assertions.assertTrue(testSet.contains(TestEnum.C)); - Assertions.assertEquals(val, testSet.toInt()); + Assertions.assertEquals(val, testSet.intValue()); } - enum TestEnum implements EnumInteger { + enum TestEnum implements MaskValueEnum { A(0x01), B(0x08), C(0x110), @@ -30,7 +29,7 @@ enum TestEnum implements EnumInteger { } @Override - public int getMask() { + public int intValue() { return val; } } diff --git a/src/test/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptorTest.java b/src/test/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptorTest.java index 4bb70ae7..6dc7c64b 100644 --- a/src/test/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptorTest.java +++ b/src/test/java/dev/dokan/dokan_java/structure/filesecurity/SelfRelativeSecurityDescriptorTest.java @@ -5,7 +5,7 @@ import dev.dokan.dokan_java.constants.microsoft.filesecurity.AccessControlEntryFlag; import dev.dokan.dokan_java.constants.microsoft.filesecurity.SecurityDescriptorControlFlag; import dev.dokan.dokan_java.constants.microsoft.filesecurity.SidIdentifierAuthority; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -24,13 +24,12 @@ public class SelfRelativeSecurityDescriptorTest { @Test public void testControlField() { - EnumIntegerSet control = new EnumIntegerSet<>(SecurityDescriptorControlFlag.class); - control.add(SecurityDescriptorControlFlag.GD, SecurityDescriptorControlFlag.OD, SecurityDescriptorControlFlag.DD, SecurityDescriptorControlFlag.SD); + MaskValueSet control = MaskValueSet.of(SecurityDescriptorControlFlag.GD, SecurityDescriptorControlFlag.OD, SecurityDescriptorControlFlag.DD, SecurityDescriptorControlFlag.SD); ByteBuffer buf = ByteBuffer.allocate(2); - Assertions.assertEquals((43 << 8 + 0) << 16, Integer.reverseBytes(control.toInt())); - Assertions.assertEquals((43 << 8 + 0), Short.reverseBytes((short) control.toInt())); - Assertions.assertArrayEquals(new byte[]{43, 0}, buf.putShort(Short.reverseBytes((short) control.toInt())).array()); + Assertions.assertEquals((43 << 8 + 0) << 16, Integer.reverseBytes(control.intValue())); + Assertions.assertEquals((43 << 8 + 0), Short.reverseBytes((short) control.intValue())); + Assertions.assertArrayEquals(new byte[]{43, 0}, buf.putShort(Short.reverseBytes((short) control.intValue())).array()); } @Test @@ -64,11 +63,9 @@ public void testSidFromString() { @Test public void testAccessAllowedACE() { //set the flag - EnumIntegerSet flags = new EnumIntegerSet(AccessControlEntryFlag.class); - flags.add(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); + MaskValueSet flags = MaskValueSet.of(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); //set the mask - EnumIntegerSet mask = new EnumIntegerSet<>(AccessMask.class); - mask.add(AccessMask.GENERIC_ALL); + MaskValueSet mask = MaskValueSet.of(AccessMask.GENERIC_ALL); //set the sid to world sid resp. everyone SecurityIdentifier sid = SecurityIdentifier.fromString("S-1-1-0");// everyone sid //create ace @@ -92,11 +89,9 @@ public void testACL() { Assertions.assertArrayEquals(new byte[]{0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, emptySaclRev4.toByteArray()); //test DACL rev2 with accessAllowACE - EnumIntegerSet flags = new EnumIntegerSet(AccessControlEntryFlag.class); - flags.add(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); + MaskValueSet flags = MaskValueSet.of(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); //set the mask - EnumIntegerSet mask = new EnumIntegerSet<>(AccessMask.class); - mask.add(AccessMask.GENERIC_ALL); + MaskValueSet mask = MaskValueSet.of(AccessMask.GENERIC_ALL); //set the sid to world sid resp. everyone SecurityIdentifier sid = SecurityIdentifier.fromString("S-1-1-0"); //create ace @@ -107,8 +102,7 @@ public void testACL() { @Test public void testEmptySecurityDescriptor() { - EnumIntegerSet flags = new EnumIntegerSet<>(SecurityDescriptorControlFlag.class); - flags.add(SecurityDescriptorControlFlag.GD, SecurityDescriptorControlFlag.OD, SecurityDescriptorControlFlag.DD, SecurityDescriptorControlFlag.SD); + MaskValueSet flags = MaskValueSet.of(SecurityDescriptorControlFlag.GD, SecurityDescriptorControlFlag.OD, SecurityDescriptorControlFlag.DD, SecurityDescriptorControlFlag.SD); byte[] expected = getEmptySelfRelativeSecurityDescriptorWithEmptyFlags(); expected[2] = 43; Assertions.assertArrayEquals(expected, SelfRelativeSecurityDescriptor.createEmptySD(flags).toByteArray()); @@ -117,8 +111,7 @@ public void testEmptySecurityDescriptor() { @Test public void testOwnerAndGroupSD() { //control - EnumIntegerSet control = new EnumIntegerSet<>(SecurityDescriptorControlFlag.class); - control.add(SecurityDescriptorControlFlag.SR, SecurityDescriptorControlFlag.SD, SecurityDescriptorControlFlag.DD); + MaskValueSet control = MaskValueSet.of(SecurityDescriptorControlFlag.SR, SecurityDescriptorControlFlag.SD, SecurityDescriptorControlFlag.DD); //owner SecurityIdentifier oSid = SecurityIdentifier.fromString("S-1-1-0"); //group @@ -140,18 +133,15 @@ public void testOwnerAndGroupSD() { @Test public void testSDWithOwnerGroupAndDacl() { //control - EnumIntegerSet control = new EnumIntegerSet<>(SecurityDescriptorControlFlag.class); - control.add(SecurityDescriptorControlFlag.SR, SecurityDescriptorControlFlag.DP, SecurityDescriptorControlFlag.SD); + MaskValueSet control = MaskValueSet.of(SecurityDescriptorControlFlag.SR, SecurityDescriptorControlFlag.DP, SecurityDescriptorControlFlag.SD); //owner SecurityIdentifier oSid = SecurityIdentifier.fromString("S-1-1-0"); SecurityIdentifier gSid = SecurityIdentifier.fromString("S-1-1-0"); //ace //ace control - EnumIntegerSet flags = new EnumIntegerSet<>(AccessControlEntryFlag.class); - flags.add(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); + MaskValueSet flags = MaskValueSet.of(AccessControlEntryFlag.CONTAINER_INHERIT_ACE, AccessControlEntryFlag.OBJECT_INHERIT_ACE); //set the mask - EnumIntegerSet mask = new EnumIntegerSet<>(AccessMask.class); - mask.add(AccessMask.GENERIC_ALL); + MaskValueSet mask = MaskValueSet.of(AccessMask.GENERIC_ALL); //create ace AccessControlList daclRev2WithAccessAllow = AccessControlList.createDaclRevision2(Collections.singletonList(new AccessAllowedACE(flags, oSid, mask)));