From 665adea5f27b294d0c3146efd3190843c1f16fe5 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 2 May 2020 19:06:49 +0200 Subject: [PATCH 01/25] Made isImplemented()-method public --- .../java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java b/src/main/java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java index 613c6424..7e3ea544 100644 --- a/src/main/java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java @@ -219,7 +219,7 @@ private void init(DokanyOperations dokanyOperations) { } } - private boolean isImplemented(String funcName) { + public boolean isImplemented(String funcName) { return !notImplementedMethods.contains(funcName); } From 97bb43219e77739f5f304742e0b82edd63a71f7a Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 2 May 2020 19:07:15 +0200 Subject: [PATCH 02/25] Re-added API for conversion from FileTime to FILETIME Re-added API for conversion from java.nio.file.attribute.FileTime to com.sun.jna.platform.win32.WinBase.FILETIME --- src/main/java/dev/dokan/dokan_java/DokanyUtils.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/dev/dokan/dokan_java/DokanyUtils.java b/src/main/java/dev/dokan/dokan_java/DokanyUtils.java index c0a91c5d..6d92857f 100644 --- a/src/main/java/dev/dokan/dokan_java/DokanyUtils.java +++ b/src/main/java/dev/dokan/dokan_java/DokanyUtils.java @@ -4,6 +4,7 @@ import com.sun.jna.platform.win32.WinNT; import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; +import java.nio.file.attribute.FileTime; import java.util.Date; import static com.sun.jna.platform.win32.WinError.*; @@ -50,6 +51,10 @@ public static String trimStrToSize(final String str, final int len) { return str.substring(0, Math.min(str.length(), len)); } + public static FILETIME toFILETIME(final FileTime time) { + return getTime(time.toMillis()); + } + public static FILETIME getTime(final Date date) { return new FILETIME(date); } From ecda6a63cd8621435888fa8f3e92117d6134d2fd Mon Sep 17 00:00:00 2001 From: JaniruTec <52893617+JaniruTEC@users.noreply.github.com> Date: Mon, 4 May 2020 19:06:18 +0200 Subject: [PATCH 03/25] Updated README.md with info about versioning --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 38f51f29..c7c252ff 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,15 @@ To publish to a local Maven repository, execute as the third step `./gradlew.bat ## Examples Example user filesystems using this library, see the examples package [dev.dokan.dokan_java.examples](https://github.com/dokan-dev/dokan-java/tree/develop/src/main/java/dev/dokan/dokan_java/examples). +## Versioning +Dokan-Java uses it's own versioning system and therefore doesn't match the versions of Dokany. +For Dokan-Java to work you need to have a suitable version of Dokany installed on your machine. The following table helps you choose the correct Dokany-version. + +| Dokan-Java Version | Minimum Version of Dokany | +|--------------------|---------------------------| +| 1.0.0 - 1.1.X | 1.2.0.1000 | +| 1.2.0+ | 1.3.0.1000 | + ## Contributing You're encouraged to contribute. Fork the code and then submit a pull request. From 64f66e48afcead5b172a883d14f5984a1aa185c5 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Tue, 5 May 2020 18:24:07 +0200 Subject: [PATCH 04/25] Added multiple Enums to wrap native bitmasks Added DokanFileInfoFlag to aid in creating a wrapper ("DokanFileHandle") for DokanFileInfo's getters (e.g. isDirectory()) Added FileShareAccess to wrap paramter rawShareAccess of DokanyFileSystem#zwCreateFile to aid in creating a wrapper ("EasyDokanFileSystem") for DokanyFileSystem Added MicrosoftReparsePointTag to wrap field dwReserved0 of WinBase.WIN32_FIND_DATA to aid in creating a wrappe ("FindFileInfo") for WinBase.WIN32_FIND_DATA (used by DokanyFileSystem#findFiles) This commit is part of my effort to fix dokan-java's issue 32 (https://github.com/dokan-dev/dokan-java/issues/32): Adding wrappers for high-level programming --- gradle.properties | 2 +- .../constants/dokany/DokanFileInfoFlag.java | 27 ++++++++++++++++ .../constants/microsoft/FileShareAccess.java | 21 ++++++++++++ .../microsoft/MicrosoftReparsePointTag.java | 32 +++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java create mode 100644 src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java create mode 100644 src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java diff --git a/gradle.properties b/gradle.properties index 90386a6d..1bad6f10 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ name=dokan-java -version=1.1.1 +version=1.2.0-SNAPSHOT group=dev.dokan artifact=dokan-java description=A Java wrapper for Dokany (https://dokan-dev.github.io/) diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java new file mode 100644 index 00000000..4dc080b1 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java @@ -0,0 +1,27 @@ +package dev.dokan.dokan_java.constants.dokany; + +import dev.dokan.dokan_java.constants.EnumInteger; + +/** + * [TO BE REPLACED WITH LICENSE NOTE] + */ +public enum DokanFileInfoFlag implements EnumInteger { + + DELETE_ON_CLOSE(1), + IS_DIRECTORY(2), + NO_CACHE(4), + PAGING_IO(8), + SYNCHRONOUS_IO(16), + WRITE_TO_END_OF_FILE(32); + + private final int mask; + + DokanFileInfoFlag(int mask) { + this.mask = mask; + } + + @Override + public int getMask() { + return this.mask; + } +} diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java new file mode 100644 index 00000000..3efc96b3 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java @@ -0,0 +1,21 @@ +package dev.dokan.dokan_java.constants.microsoft; + +import dev.dokan.dokan_java.constants.EnumInteger; + +public enum FileShareAccess implements EnumInteger { + + FILE_SHARE_READ(1), + FILE_SHARE_WRITE(2), + FILE_SHARE_DELETE(4); + + private final int mask; + + FileShareAccess(int mask) { + this.mask = mask; + } + + @Override + public int getMask() { + return this.mask; + } +} diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java new file mode 100644 index 00000000..0e68e063 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java @@ -0,0 +1,32 @@ +package dev.dokan.dokan_java.constants.microsoft; + +import dev.dokan.dokan_java.constants.EnumInteger; + +/** + * [TO BE REPLACED WITH LICENSE NOTE] + */ +public enum MicrosoftReparsePointTag implements EnumInteger { + + IO_REPARSE_TAG_CSV(0x80000009), + IO_REPARSE_TAG_DEDUP(0x80000013), + IO_REPARSE_TAG_DFS(0x8000000A), + IO_REPARSE_TAG_DFSR(0x80000012), + IO_REPARSE_TAG_HSM(0xC0000004), + IO_REPARSE_TAG_HSM2(0x80000006), + IO_REPARSE_TAG_MOUNT_POINT(0xA0000003), + IO_REPARSE_TAG_NFS(0x80000014), + IO_REPARSE_TAG_SIS(0x80000007), + IO_REPARSE_TAG_SYMLINK(0xA000000C), + IO_REPARSE_TAG_WIM(0x80000008); + + private final int mask; + + MicrosoftReparsePointTag(int mask) { + this.mask = mask; + } + + @Override + public int getMask() { + return this.mask; + } +} From caf890ce885010efa045fa3c88907c6e52c8092f Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 7 May 2020 20:35:22 +0200 Subject: [PATCH 05/25] Added FileInfo-API Added EasyFileInfo to wrap the result of DokanyFileSystem#getFileInformation (ByHandleFileInformation) and Added FindFileInfo to wrap the result of DokanyFileSystem#findFiles (WinBase.WIN32_FIND_DATA) to aid in creating a wrapper ("EasyDokanFileSystem") for DokanyFileSystem Added AbstractFileInfo as common base class for FileInfos (like EasyFileInfo and FindFileInfo) Added DefaultFileTimePolicy to help in returning valid FileTimes to Dokan if unavailable to AbstractFileInfo This commit is part of my effort to fix dokan-java's issue 32 (https://github.com/dokan-dev/dokan-java/issues/32): Adding wrappers for high-level programming --- .../dokan_java/DefaultFileTimePolicy.java | 13 ++ .../dokan_java/wrappers/AbstractFileInfo.java | 166 ++++++++++++++++++ .../dokan_java/wrappers/EasyFileInfo.java | 87 +++++++++ .../dokan_java/wrappers/FindFileInfo.java | 147 ++++++++++++++++ 4 files changed, 413 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java b/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java new file mode 100644 index 00000000..2031d97c --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java @@ -0,0 +1,13 @@ +package dev.dokan.dokan_java.constants.dokan_java; + +/** + * [TO BE REPLACED WITH LICENSE NOTE] + */ +public enum DefaultFileTimePolicy { + + STATIC_YEAR_1601, + STATIC_YEAR_1970, + INHERIT_ELSE_1601, + INHERIT_ELSE_1970 + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java new file mode 100644 index 00000000..d4535977 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java @@ -0,0 +1,166 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.constants.dokan_java.DefaultFileTimePolicy; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +import java.nio.file.attribute.FileTime; +import java.util.concurrent.atomic.AtomicInteger; + +public class AbstractFileInfo { + + //See field by same name in com.sun.jna.platform.win32.WinBase.FILETIME; + private final static long WINDOWS_EPOCH_0 = -11644473600000L; + private final static long UNIX_EPOCH_0 = 0; + + private final static FileTime YEAR_1601 = FileTime.fromMillis(WINDOWS_EPOCH_0); + private final static FileTime YEAR_1970 = FileTime.fromMillis(UNIX_EPOCH_0); + + private final AtomicInteger fileAttributes; + + private FileTime creationTime; + private FileTime lastAccessTime; + private FileTime lastWriteTime; + + private DefaultFileTimePolicy fileTimePolicy = DefaultFileTimePolicy.INHERIT_ELSE_1970; + private long fileSize; + + public AbstractFileInfo(EnumIntegerSet attributes) { + this(attributes.isEmpty() ? FileAttribute.NORMAL.getMask() : attributes.toInt()); + } + + public AbstractFileInfo(int attributes) { + this.fileAttributes = new AtomicInteger(attributes); + } + + public int getFlags() { + return this.fileAttributes.get(); + } + + public void setFlags(int flags) { + this.fileAttributes.set(flags); + } + + public EnumIntegerSet getFileAttributes() { + return EnumIntegerSet.enumSetFromInt(this.fileAttributes.get(), FileAttribute.values()); + } + + public boolean getFlag(FileAttribute flag) { + return (this.fileAttributes.get() & flag.getMask()) != 0; + } + + public boolean setFlag(FileAttribute flag) { + return updateFlag(flag, true); + } + + public boolean unsetFlag(FileAttribute flag) { + return updateFlag(flag, false); + } + + public boolean updateFlag(FileAttribute flag, boolean value) { + int prev = this.fileAttributes.getAndUpdate(current -> current & (value ? flag.getMask() : ~flag.getMask())); + return (prev & flag.getMask()) != 0; + } + + public void setTimes(long creationTime, long lastAccessTime, long lastWriteTime) { + setCreationTime(creationTime); + setLastAccessTime(lastAccessTime); + setLastWriteTime(lastWriteTime); + } + + public void setTimes(FileTime creationTime, FileTime lastAccessTime, FileTime lastWriteTime) { + setCreationTime(creationTime); + setLastAccessTime(lastAccessTime); + setLastWriteTime(lastWriteTime); + } + + public FileTime getStaticCreationTime() { + return this.creationTime; + } + + public FileTime getCreationTime() { + if(this.creationTime != null) { + return this.creationTime; + } + return getAlternateTime(); + } + + public void setCreationTime(FileTime creationTime) { + this.creationTime = creationTime; + } + + public void setCreationTime(long millis) { + setCreationTime(FileTime.fromMillis(millis)); + } + + public FileTime getStaticLastWriteTime() { + return this.lastWriteTime; + } + + public FileTime getLastWriteTime() { + if(this.lastWriteTime != null) { + return this.lastWriteTime; + } + return getAlternateTime(); + } + + public void setLastWriteTime(FileTime lastWriteTime) { + this.lastWriteTime = lastWriteTime; + } + + public void setLastWriteTime(long millis) { + setLastWriteTime(FileTime.fromMillis(millis)); + } + + public FileTime getStaticLastAccessTime() { + return this.lastAccessTime; + } + + public FileTime getLastAccessTime() { + if(this.lastAccessTime != null) { + return this.lastAccessTime; + } + return getAlternateTime(); + } + + public void setLastAccessTime(FileTime lastAccessTime) { + this.lastAccessTime = lastAccessTime; + } + + public void setLastAccessTime(long millis) { + setLastAccessTime(FileTime.fromMillis(millis)); + } + + public long getFileSize() { + return this.fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + private FileTime getAlternateTime() { + if(this.fileTimePolicy == DefaultFileTimePolicy.STATIC_YEAR_1601) { + return YEAR_1601; + } + if(this.fileTimePolicy == DefaultFileTimePolicy.STATIC_YEAR_1970) { + return YEAR_1970; + } + + //--> Inheritance + //#1 Priority: Last write Time + if(this.lastWriteTime != null) { + return this.lastWriteTime; + } + //#2 Priority: Creation Time + if(this.creationTime != null) { + return this.creationTime; + } + //#3 Priority: Access Time + if(this.lastAccessTime != null) { + return this.lastAccessTime; + } + //#4 Resort to default time by policy + return this.fileTimePolicy == DefaultFileTimePolicy.INHERIT_ELSE_1601 ? YEAR_1601 : YEAR_1970; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java new file mode 100644 index 00000000..4216ca33 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java @@ -0,0 +1,87 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.structure.ByHandleFileInformation; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +import java.nio.file.Path; + +/** + * [TO BE REPLACED WITH LICENSE NOTE] + */ +public class EasyFileInfo extends AbstractFileInfo { + + private final Path path; + + private int volumeSerialNumber; + private long fileIndex; + private int numberOfLinks; + + public EasyFileInfo(Path path) { + this(path, FileAttribute.NORMAL.getMask()); + } + + public EasyFileInfo(Path path, EnumIntegerSet attributes) { + super(attributes); + this.path = path; + } + + public EasyFileInfo(Path path, int attributes) { + super(attributes); + this.path = path; + } + + public Path getPath() { + return this.path; + } + + public int getVolumeSerialNumber() { + return this.volumeSerialNumber; + } + + public void setVolumeSerialNumber(int volumeSerialNumber) { + this.volumeSerialNumber = volumeSerialNumber; + } + + public long getFileIndex() { + return this.fileIndex; + } + + public void setFileIndex(long fileIndex) { + this.fileIndex = fileIndex; + } + + public int getNumberOfLinks() { + return this.numberOfLinks; + } + + public void setNumberOfLinks(int numberOfLinks) { + this.numberOfLinks = numberOfLinks; + } + + public ByHandleFileInformation toByHandleFileInformation() { + return toByHandleFileInformation(this.path); + } + + public ByHandleFileInformation toByHandleFileInformation(Path pathOverride) { + ByHandleFileInformation info = new ByHandleFileInformation(pathOverride, + getFlags(), + getCreationTime(), + getLastAccessTime(), + getLastWriteTime(), + this.volumeSerialNumber, + getFileSize(), + this.fileIndex); + info.nNumberOfLinks = this.numberOfLinks; + + return info; + } + + public void copyTo(ByHandleFileInformation byHandleFileInformation) { + copyTo(byHandleFileInformation, this.path); + } + + public void copyTo(ByHandleFileInformation byHandleFileInformation, Path pathOverride) { + toByHandleFileInformation(pathOverride).copyTo(byHandleFileInformation); //That's not the most efficient way to do this, but it's less prone to human error + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java new file mode 100644 index 00000000..60ebc350 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java @@ -0,0 +1,147 @@ +package dev.dokan.dokan_java.wrappers; + +import com.sun.jna.platform.win32.WinBase; +import dev.dokan.dokan_java.DokanyUtils; +import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.constants.microsoft.MicrosoftReparsePointTag; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +import java.util.Objects; +import java.util.function.Function; + +/** + * [TO BE REPLACED WITH LICENSE NOTE] + */ +public class FindFileInfo extends AbstractFileInfo { + + private static final int MAX_ALTERNATIVE_NAME_LENGTH = 14; + private static final FileAttribute REPARSE_POINT_FLAG = FileAttribute.REPARSE_POINT; + private static final String REPARSE_POINT_NOT_SET_MESSAGE = + "Reparse point tags are disabled on this File(-Handle); Flag \"FileAttribute.REPARSE_POINT\" not set"; + private final int RESERVED_1_FIELD_DEFAULT = 0; + + private int reparsePointTag; + // private int reserved_1; //Not yet specified by Microsoft + private String fileName; + private String alternativeName; + + public FindFileInfo(EnumIntegerSet attributes) { + super(attributes); + } + + public FindFileInfo(int attributes) { + super(attributes); + } + + public int getReparsePointTagValueLeniently() { + return getReparsePointFlag() ? this.reparsePointTag : 0; + } + + public int getReparsePointTagValue() { + tryReparsePoint(); + return this.reparsePointTag; + } + + public void setReparsePointTagValue(int reparsePointTagValue) { + tryReparsePoint(); + this.reparsePointTag = reparsePointTagValue; + } + + public MicrosoftReparsePointTag getMSReparsePointTag() { + return getReparsePointTag(MicrosoftReparsePointTag.values()); + } + + public void setMSReparsePointTag(MicrosoftReparsePointTag tag) { + setReparsePointTag(tag); + } + + public T getReparsePointTag(T[] possibleValues) { + return EnumInteger.enumFromInt(getReparsePointTagValue(), possibleValues); + } + + public void setReparsePointTag(T tag) { + setReparsePointTagValue(tag.getMask()); + } + + public > T getReparsePointTag(Function parser) { + return parser.apply(getReparsePointTagValue()); + } + + public > void setReparsePointTag(T tag, Function parser) { + setReparsePointTagValue(parser.apply(tag)); + } + + public boolean getReparsePointFlag() { + return getFlag(REPARSE_POINT_FLAG); + } + + public boolean setReparsePointFlag() { + return updateReparsePointFlag(true); + } + + public boolean unsetReparsePointFlag() { + return updateReparsePointFlag(false); + } + + public boolean updateReparsePointFlag(boolean value) { + /* + * The previous tag value is not discarded when updating the flag to false. + * But: The tag value will only be present in the WIN32_FIND_DATA if the flag is set to true. + * The following code could change that behavior. + * + * if(value && (prevValueFromUpdate != value)) { setReparsePointTagValue(0); } + */ + return updateFlag(REPARSE_POINT_FLAG, value); + } + + public String getFileName() { + return this.fileName; + } + + public void setFileName(String fileName) { + this.fileName = Objects.requireNonNullElse(fileName, ""); + } + + public String getAlternativeName() { + return this.alternativeName; + } + + public void setAlternativeName(String alternativeName) { + alternativeName = Objects.requireNonNullElse(alternativeName, ""); + if(alternativeName.length() > 14) { + throw new IllegalArgumentException("Alternative name must not be longer than 14 chars"); + } + this.alternativeName = alternativeName; + } + + public String setAlternativeNameLeniently(String alternativeName) { + alternativeName = Objects.requireNonNullElse(alternativeName, ""); + this.alternativeName = alternativeName.substring(0, MAX_ALTERNATIVE_NAME_LENGTH); + + return this.alternativeName; + } + + public WinBase.WIN32_FIND_DATA toWIN32_FIND_DATA() { + long fileSize = getFileSize(); + int fileSizeHigh = (int) (fileSize >> 32 & 0xffffffffL); + int fileSizeLow = (int) (fileSize & 0xffffffffL); + + return new WinBase.WIN32_FIND_DATA(getFlags(), + DokanyUtils.toFILETIME(getCreationTime()), + DokanyUtils.toFILETIME(getLastAccessTime()), + DokanyUtils.toFILETIME(getLastWriteTime()), + fileSizeHigh, + fileSizeLow, + getReparsePointTagValueLeniently(), + this.RESERVED_1_FIELD_DEFAULT, + this.fileName.toCharArray(), + this.alternativeName.toCharArray()); + } + + private void tryReparsePoint() { + if(!getReparsePointFlag()) { + throw new IllegalStateException(REPARSE_POINT_NOT_SET_MESSAGE); + } + } +} \ No newline at end of file From 495e9cddbffdbbfd74a1ef3ef60df61a4b3ce93b Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 7 May 2020 21:22:33 +0200 Subject: [PATCH 06/25] Readded VolumeInformation Restored VolumeInformation from commit 99bcbda75c0ef67505083025a569fc385dc5cfb3 (party reverting commit 3c343ebd4df6d977c41a1caf0669f5ca4a6068b0) to wrap the result of DokanyFileSystem#getVolumeInformation to aid in creating a wrapper ("EasyDokanFileSystem") for DokanyFileSystem This commit is part of my effort to fix dokan-java's issue 32 (https://github.com/dokan-dev/dokan-java/issues/32): Adding wrappers for high-level programming --- .../legacy/structure/VolumeInformation.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java diff --git a/src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java b/src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java new file mode 100644 index 00000000..3eeb7d17 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java @@ -0,0 +1,113 @@ +package dev.dokan.dokan_java.legacy.structure; + +import dev.dokan.dokan_java.DokanyOperations; +import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +/** + * Supplementary class to bundle information of the mounted volume and its filesystem. + *

Mainly used for {@link DokanyOperations#GetVolumeInformation} function to have all needed information at one place.

+ * TODO: Maybe this can be completely integrated in the DokanyFileSystem class + */ +public final class VolumeInformation { + private final int maxComponentLength; + private final String name; + private final int serialNumber; + private final String fileSystemName; + private final EnumIntegerSet fileSystemFeatures; + + public static final int DEFAULT_MAX_COMPONENT_LENGTH = 256; + public static final int DEFAULT_SERIAL_NUMBER = 305419896; + public static final String DEFAULT_VOLUME_NAME = "VOLUME1"; + public static final String DEFAULT_FS_NAME = "DOKANY"; + public static final EnumIntegerSet DEFAULT_FS_FEATURES = new EnumIntegerSet<>(FileSystemFlag.class); + + static { + DEFAULT_FS_FEATURES.add(FileSystemFlag.CASE_PRESERVED_NAMES); + } + + /** + * Provides default values for maxComponentLength and fileSystemFeatures. + * + * @param volumeName + * @param serialNumber + * @param fileSystemName + */ + public VolumeInformation(final String volumeName, final int serialNumber, final String fileSystemName) { + this(DEFAULT_MAX_COMPONENT_LENGTH, volumeName, serialNumber, fileSystemName, DEFAULT_FS_FEATURES); + } + + /** + * Provides default values for all values. + */ + public VolumeInformation() { + this(DEFAULT_MAX_COMPONENT_LENGTH, DEFAULT_VOLUME_NAME, DEFAULT_SERIAL_NUMBER, DEFAULT_FS_NAME, DEFAULT_FS_FEATURES); + } + + public int getMaxComponentLength() { + return this.maxComponentLength; + } + + public String getName() { + return this.name; + } + + public int getSerialNumber() { + return this.serialNumber; + } + + public String getFileSystemName() { + return this.fileSystemName; + } + + public EnumIntegerSet getFileSystemFeatures() { + return this.fileSystemFeatures; + } + + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof VolumeInformation)) return false; + final VolumeInformation other = (VolumeInformation) o; + if (this.getMaxComponentLength() != other.getMaxComponentLength()) return false; + final Object this$name = this.getName(); + final Object other$name = other.getName(); + if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; + if (this.getSerialNumber() != other.getSerialNumber()) return false; + final Object this$fileSystemName = this.getFileSystemName(); + final Object other$fileSystemName = other.getFileSystemName(); + if (this$fileSystemName == null ? other$fileSystemName != null : !this$fileSystemName.equals(other$fileSystemName)) return false; + final Object this$fileSystemFeatures = this.getFileSystemFeatures(); + final Object other$fileSystemFeatures = other.getFileSystemFeatures(); + if (this$fileSystemFeatures == null ? other$fileSystemFeatures != null : !this$fileSystemFeatures.equals(other$fileSystemFeatures)) return false; + return true; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.getMaxComponentLength(); + final Object $name = this.getName(); + result = result * PRIME + ($name == null ? 43 : $name.hashCode()); + result = result * PRIME + this.getSerialNumber(); + final Object $fileSystemName = this.getFileSystemName(); + result = result * PRIME + ($fileSystemName == null ? 43 : $fileSystemName.hashCode()); + final Object $fileSystemFeatures = this.getFileSystemFeatures(); + result = result * PRIME + ($fileSystemFeatures == null ? 43 : $fileSystemFeatures.hashCode()); + return result; + } + + @Override + public String toString() { + return "VolumeInformation(maxComponentLength=" + this.getMaxComponentLength() + ", name=" + this.getName() + ", serialNumber=" + this.getSerialNumber() + ", fileSystemName=" + this.getFileSystemName() + ", fileSystemFeatures=" + this.getFileSystemFeatures() + ")"; + } + + public VolumeInformation(final int maxComponentLength, final String name, final int serialNumber, final String fileSystemName, final EnumIntegerSet fileSystemFeatures) { + this.maxComponentLength = maxComponentLength; + this.name = name; + this.serialNumber = serialNumber; + this.fileSystemName = fileSystemName; + this.fileSystemFeatures = fileSystemFeatures; + } +} From c07a5636ded2bb221d6823cb9bf0d00edcdfb167 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 7 May 2020 21:25:39 +0200 Subject: [PATCH 07/25] Moved VolumeInformation Moved VolumeInformation from original package dev.dokan.dokan_java.legacy.structure to dev.dokan.dokan_java.wrappers --- .../{legacy/structure => wrappers}/VolumeInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/dev/dokan/dokan_java/{legacy/structure => wrappers}/VolumeInformation.java (98%) diff --git a/src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java similarity index 98% rename from src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java rename to src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java index 3eeb7d17..440ed5d1 100644 --- a/src/main/java/dev/dokan/dokan_java/legacy/structure/VolumeInformation.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java @@ -1,4 +1,4 @@ -package dev.dokan.dokan_java.legacy.structure; +package dev.dokan.dokan_java.wrappers; import dev.dokan.dokan_java.DokanyOperations; import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; From a11aa0e8069a55fd1ee0d5404a8545ac72ff7a1a Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Fri, 8 May 2020 15:23:48 +0200 Subject: [PATCH 08/25] Removed misplaced license templates --- .../dokan_java/constants/dokan_java/DefaultFileTimePolicy.java | 3 --- .../dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java | 3 --- .../constants/microsoft/MicrosoftReparsePointTag.java | 3 --- src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java | 3 --- src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java | 3 --- 5 files changed, 15 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java b/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java index 2031d97c..6216784f 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java +++ b/src/main/java/dev/dokan/dokan_java/constants/dokan_java/DefaultFileTimePolicy.java @@ -1,8 +1,5 @@ package dev.dokan.dokan_java.constants.dokan_java; -/** - * [TO BE REPLACED WITH LICENSE NOTE] - */ public enum DefaultFileTimePolicy { STATIC_YEAR_1601, diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java index 4dc080b1..7e5715d8 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java @@ -2,9 +2,6 @@ import dev.dokan.dokan_java.constants.EnumInteger; -/** - * [TO BE REPLACED WITH LICENSE NOTE] - */ public enum DokanFileInfoFlag implements EnumInteger { DELETE_ON_CLOSE(1), diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java index 0e68e063..808650a4 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java @@ -2,9 +2,6 @@ import dev.dokan.dokan_java.constants.EnumInteger; -/** - * [TO BE REPLACED WITH LICENSE NOTE] - */ public enum MicrosoftReparsePointTag implements EnumInteger { IO_REPARSE_TAG_CSV(0x80000009), diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java index 4216ca33..1a31a54e 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java @@ -6,9 +6,6 @@ import java.nio.file.Path; -/** - * [TO BE REPLACED WITH LICENSE NOTE] - */ public class EasyFileInfo extends AbstractFileInfo { private final Path path; diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java index 60ebc350..b58dbf99 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java @@ -10,9 +10,6 @@ import java.util.Objects; import java.util.function.Function; -/** - * [TO BE REPLACED WITH LICENSE NOTE] - */ public class FindFileInfo extends AbstractFileInfo { private static final int MAX_ALTERNATIVE_NAME_LENGTH = 14; From fb4489bded8691cab0fc8894e72fe014093f8b15 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 9 May 2020 16:44:37 +0200 Subject: [PATCH 09/25] Added DesiredAccessMask and DiskSpaceInfo Added DesiredAccessMask to wrap parameter desiredAccess of DokanyFileSystem#zwCreateFile to aid in creating a wrapper ("EasyDokanFileSystem") for DokanyFileSystem Added DiskSpaceInfo to wrap the result of DokanyFileSystem#getDiskFreeSpace to aid in creating a wrapper ("EasyDokanFileSystem") for DokanyFileSystem This commit is part of my effort to fix dokan-java's issue 32 (https://github.com/dokan-dev/dokan-java/issues/32): Adding wrappers for high-level programming --- .../wrappers/DesiredAccessMask.java | 146 ++++++++++++++++++ .../dokan_java/wrappers/DiskSpaceInfo.java | 42 +++++ 2 files changed, 188 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/DiskSpaceInfo.java diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java new file mode 100644 index 00000000..83b54eee --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -0,0 +1,146 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.constants.microsoft.AccessMask; +import dev.dokan.dokan_java.constants.microsoft.DirectoryAccessMask; +import dev.dokan.dokan_java.constants.microsoft.FileAccessMask; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +import java.util.concurrent.atomic.AtomicInteger; + +public class DesiredAccessMask { + + private final boolean isDirectory; + private final AtomicInteger accessMask; + + public DesiredAccessMask(int rawAccessMask, int rawFileAttributes) { + this(rawAccessMask, (rawFileAttributes & FileAttribute.DIRECTORY.getMask()) != 0); + } + + public DesiredAccessMask(int rawAccessMask, EnumIntegerSet fileAttributes) { + this(rawAccessMask, fileAttributes.contains(FileAttribute.DIRECTORY)); + } + + //TODO Check for illegal flags if isDirectory=true + //See https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatefile Note below first table + public DesiredAccessMask(int rawAccessMask, boolean isDirectory) { + this.isDirectory = isDirectory; + this.accessMask = new AtomicInteger(rawAccessMask); + } + + public EnumIntegerSet getBasicRights() { + return EnumIntegerSet.enumSetFromInt(this.accessMask.get(), AccessMask.values()); + } + + public EnumIntegerSet getSpecificRights() { + return EnumIntegerSet.enumSetFromInt(this.accessMask.get(), FileAccessMask.values()); + } + + public boolean isDirectory() { + return this.isDirectory; + } + + public int getAccessMask() { + return this.accessMask.get(); + } + + public void setAccessMask(int accessMask) { + this.accessMask.set(accessMask); + } + + public boolean getFlag(AccessMask flag) { + return getFlag(flag.getMask()); + } + + public boolean getFlag(FileAccessMask flag) { + return getFlag(flag.getMask()); + } + + public boolean getFlag(DirectoryAccessMask flag) { + if(!this.isDirectory) { + throw new IllegalArgumentException("Not a directory!"); + } + return silentGetFlag(flag); + } + + public boolean silentGetFlag(DirectoryAccessMask flag) { + return getFlag(flag.getMask()); + } + + public boolean getFlag(int flag) { + return (this.accessMask.get() & flag) != 0; + } + + public boolean setFlag(AccessMask flag) { + return updateFlag(flag, true); + } + + public boolean unsetFlag(AccessMask flag) { + return updateFlag(flag, false); + } + + public boolean updateFlag(AccessMask flag, boolean value) { + return updateFlag(flag.getMask(), value); + } + + public boolean setFlag(FileAccessMask flag) { + return updateFlag(flag, true); + } + + public boolean unsetFlag(FileAccessMask flag) { + return updateFlag(flag, false); + } + + public boolean updateFlag(FileAccessMask flag, boolean value) { + return updateFlag(flag.getMask(), value); + } + + public boolean setFlag(DirectoryAccessMask flag) { + if(!this.isDirectory) { + throw new IllegalArgumentException("Not a directory!"); + } + return silentSetFlag(flag); + } + + public boolean unsetFlag(DirectoryAccessMask flag) { + if(!this.isDirectory) { + throw new IllegalArgumentException("Not a directory!"); + } + return silentUnsetFlag(flag); + } + + public boolean updateFlag(DirectoryAccessMask flag, boolean value) { + if(!this.isDirectory) { + throw new IllegalArgumentException("Not a directory!"); + } + return silentUpdateFlag(flag, value); + } + + public boolean silentSetFlag(DirectoryAccessMask flag) { + return silentUpdateFlag(flag, true); + } + + public boolean silentUnsetFlag(DirectoryAccessMask flag) { + return silentUpdateFlag(flag, false); + } + + public boolean silentUpdateFlag(DirectoryAccessMask flag, boolean value) { + return updateFlag(flag.getMask(), value); + } + + public boolean updateFlag(int flag, boolean value) { + int prev = this.accessMask.getAndUpdate(current -> current & (value ? flag : ~flag)); + return (prev & flag) != 0; + } + + private FileAccessMask getFileAccessMask(DirectoryAccessMask attribute) { + //This lookup is fine, but a different kind of mapping would be preferable + switch(attribute) { + case LIST_DIRECTORY: //1 + return FileAccessMask.READ_DATA; + case TRAVERSE: //32 + return FileAccessMask.EXECUTE; + } + throw new IllegalStateException(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DiskSpaceInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/DiskSpaceInfo.java new file mode 100644 index 00000000..10196c25 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DiskSpaceInfo.java @@ -0,0 +1,42 @@ +package dev.dokan.dokan_java.wrappers; + +public class DiskSpaceInfo { + + private long usableSpace; + private long totalSpace; + private long unallocatedSpace; + + public DiskSpaceInfo() { + this(0L, 0L, 0L); + } + + public DiskSpaceInfo(long usableSpace, long totalSpace, long unallocatedSpace) { + this.usableSpace = usableSpace; + this.totalSpace = totalSpace; + this.unallocatedSpace = unallocatedSpace; + } + + public long getUsableSpace() { + return this.usableSpace; + } + + public void setUsableSpace(long usableSpace) { + this.usableSpace = usableSpace; + } + + public long getTotalSpace() { + return this.totalSpace; + } + + public void setTotalSpace(long totalSpace) { + this.totalSpace = totalSpace; + } + + public long getUnallocatedSpace() { + return this.unallocatedSpace; + } + + public void setUnallocatedSpace(long unallocatedSpace) { + this.unallocatedSpace = unallocatedSpace; + } +} \ No newline at end of file From 08b9e890b4e2e01623329f0b42c3cb4a5776798c Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 14 May 2020 19:37:06 +0200 Subject: [PATCH 10/25] Added Filesystem and Handle Added EasyDokanyFileSystem as wrapper for DokanyFileSystem Added DokanyFileHandle to wrap parameter dokanFileInfo (DokanFileInfo) in various methods of DokanyFileSystem Added SecurityContext to wrap parameter securityContext (WinBase.SECURITY_ATTRIBUTES) of DokanyFileSystem#zwCreateFile Added Annotation NativeName to ease the use of NotImplemented on methods of EasyDokayFileSystem that have a name that differs from their counterpart in DokanyFileSystem --- .../java/dev/dokan/dokan_java/NativeName.java | 15 ++ .../dokan_java/wrappers/DokanyFileHandle.java | 112 ++++++++++++ .../wrappers/EasyDokanyFileSystem.java | 169 ++++++++++++++++++ .../dokan_java/wrappers/SecurityContext.java | 7 + 4 files changed, 303 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/NativeName.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java diff --git a/src/main/java/dev/dokan/dokan_java/NativeName.java b/src/main/java/dev/dokan/dokan_java/NativeName.java new file mode 100644 index 00000000..64acc6e2 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/NativeName.java @@ -0,0 +1,15 @@ +package dev.dokan.dokan_java; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; + +@Retention(RetentionPolicy.RUNTIME) +@Target(value = METHOD) +public @interface NativeName { + + String value(); + +} diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java b/src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java new file mode 100644 index 00000000..facf74b6 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java @@ -0,0 +1,112 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.constants.dokany.DokanFileInfoFlag; +import dev.dokan.dokan_java.structure.DokanFileInfo; +import dev.dokan.dokan_java.structure.DokanOptions; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + +import java.util.concurrent.atomic.AtomicInteger; + +public class DokanyFileHandle { //TODO Add Getters?! + + private static final long INVALID_HANDLE = 0L; + + private final AtomicInteger flags; + private final long dokanContext; //DokanFileInfo tells us to "never modify". Happy to oblige + private long context; + private int processId; + private DokanOptions dokanOpts; //TODO + + public DokanyFileHandle(DokanFileInfo nativeInfo) { + this.context = nativeInfo.Context; + this.dokanContext = nativeInfo.DokanContext; + this.processId = nativeInfo.ProcessId; + this.dokanOpts = nativeInfo.DokanOpts; //TODO Copy/Different link? + + EnumIntegerSet flagSet = new EnumIntegerSet<>(DokanFileInfoFlag.class); + if(nativeInfo.deleteOnClose()) { + flagSet.add(DokanFileInfoFlag.DELETE_ON_CLOSE); + } + if(nativeInfo.isDirectory()) { + flagSet.add(DokanFileInfoFlag.IS_DIRECTORY); + } + if(nativeInfo.noCache()) { + flagSet.add(DokanFileInfoFlag.NO_CACHE); + } + if(nativeInfo.pagingIo()) { + flagSet.add(DokanFileInfoFlag.PAGING_IO); + } + if(nativeInfo.synchronousIo()) { + flagSet.add(DokanFileInfoFlag.SYNCHRONOUS_IO); + } + if(nativeInfo.writeToEndOfFile()) { + flagSet.add(DokanFileInfoFlag.WRITE_TO_END_OF_FILE); + } + this.flags = new AtomicInteger(flagSet.toInt()); + } + + public EnumIntegerSet getFileInfo() { + return EnumIntegerSet.enumSetFromInt(this.flags.get(), DokanFileInfoFlag.values()); + } + + public int getFlags() { + return this.flags.get(); + } + + public void setFlags(int flags) { + this.flags.set(flags); + } + + public boolean getFlag(DokanFileInfoFlag flag) { + return (this.flags.get() & flag.getMask()) != 0; + } + + public boolean setFlag(DokanFileInfoFlag flag) { + return updateFlag(flag, true); + } + + public boolean unsetFlag(DokanFileInfoFlag flag) { + return updateFlag(flag, false); + } + + public boolean updateFlag(DokanFileInfoFlag flag, boolean value) { + int prev = this.flags.getAndUpdate(current -> current & (value ? flag.getMask() : ~flag.getMask())); + return (prev & flag.getMask()) != 0; + } + + public long getContext() { + return this.context; + } + + public void setContext(long context) { + this.context = context; + } + + public boolean isValid() { + return getContext() != INVALID_HANDLE; + } + + public void invalidate() { + setContext(INVALID_HANDLE); + } + + public long getDokanContext() { + return this.dokanContext; + } + + public long getProcessId() { + return this.processId; + } + + public void setProcessId(int processId) { + this.processId = processId; + } + + public DokanOptions getDokanOptions() { + return this.dokanOpts; + } + + public void setDokanOptions(DokanOptions dokanOpts) { + this.dokanOpts = dokanOpts; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java new file mode 100644 index 00000000..7f0e2495 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java @@ -0,0 +1,169 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.NativeName; +import dev.dokan.dokan_java.constants.microsoft.CreateOption; +import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.constants.microsoft.FileShareAccess; +import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.structure.filesecurity.SelfRelativeSecurityDescriptor; + +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.util.Collection; + +public interface EasyDokanyFileSystem { + + //public int zwCreateFile(WString rawPath, + // WinBase.SECURITY_ATTRIBUTES securityContext, + // int rawDesiredAccess, + // int rawFileAttributes, + // int rawShareAccess, + // int rawCreateDisposition, + // int rawCreateOptions, + // DokanFileInfo dokanFileInfo) { //TODO Return type //TODO Incorporate path into DokanFileHandle + @NativeName("zwCreateFile") + void createHandle(Path absolutePath, + String relativePath, + SecurityContext securityContext, + DesiredAccessMask desiredAccess, + EnumIntegerSet fileAttributes, + EnumIntegerSet shareAccess, + CreationDisposition creationDisposition, + EnumIntegerSet createOptions, + DokanyFileHandle dokanyFileHandle + ); //--> zwCreateFile + + @NativeName("cleanup") + void cleanup(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + + @NativeName("closeFile") + void closeHandle(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); //--> CloseFile + + @NativeName("readFile") + byte[] readFile(Path absolutePath, + String relativePath, + long offset, + int readLength, + DokanyFileHandle dokanyFileHandle); //TODO return -> callback-array? + + @NativeName("writeFile") + int writeFile(Path absolutePath, String relativePath, byte[] buffer, long offset, DokanyFileHandle dokanyFileHandle); + + @NativeName("flushFileBuffers") + void flush(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + + @NativeName("getFileInformation") + EasyFileInfo getFileInformation(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + + @NativeName("findFiles") + Collection findFiles(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + //TODO --> Collection to callback?! --> default method? + + @NativeName("findFilesWithPattern") + Collection findFilesWithPattern(Path absolutePath, + String relativePath, + String pattern, //TODO Regex + DokanyFileHandle dokanyFileHandle); + //TODO --> Collection to callback?! + + @NativeName("setFileAttributes") + void setFileAttributes(Path absolutePath, + String relativePath, + EnumIntegerSet fileAttributes, + DokanyFileHandle dokanyFileHandle); + + @NativeName("setFileTime") + void setFileTime(Path absolutePath, + String relativePath, + FileTime creationTime, + FileTime lastAccessTime, + FileTime lastWriteTime, + DokanyFileHandle dokanyFileHandle); + + @NativeName("deleteFile") + void prepareDeleteFile(Path absolutePath, + String relativePath, + DokanyFileHandle dokanyFileHandle); //TODO Rename, return value? + + @NativeName("deleteDirectory") + void prepareDeleteDirectory(Path absolutePath, + String relativePath, + DokanyFileHandle dokanyFileHandle); //TODO Rename, return value? + + @NativeName("moveFile") + void moveFile(Path sourceAbsolutePath, + String sourceRelativePath, + Path destinationAbsolutePath, + String destinationRelativePath, + boolean replaceIfExisting, + DokanyFileHandle dokanyFileHandle); + + @NativeName("setEndOfFile") + void setEndOfFile(Path absolutePath, + String relativePath, + long fileSize, + DokanyFileHandle dokanyFileHandle); + + @NativeName("setAllocationSize") + void setAllocationSize(Path absolutePath, + String relativePath, + long allocationSize, + DokanyFileHandle dokanyFileHandle); + + @NativeName("lockFile") + void lockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanyFileHandle dokanyFileHandle); + + @NativeName("unlockFile") + void unlockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanyFileHandle dokanyFileHandle); + + @NativeName("getDiskFreeSpace") + DiskSpaceInfo getDiskSpaceInfo(DokanyFileHandle dokanyFileHandle); //TODO Path? + + @NativeName("getVolumeInformation") + VolumeInformation getVolumeInformation(DokanyFileHandle dokanyFileHandle); //TODO Path? + + @NativeName("mounted") + void mounted(DokanyFileHandle dokanyFileHandle); //TODO Path? + + @NativeName("unmounted") + void unmounted(DokanyFileHandle dokanyFileHandle); //TODO Path? + + // int getFileSecurity(WString rawPath, + // int /* SecurityInformation */ rawSecurityInformation, //Requested information //DesiredAccessMask OR Similar CLASS OR EnumIntegerSet + // Pointer rawSecurityDescriptor, //Pointer to Buffer. Buffer gets copy of Security Descriptor. SECURITY_DESCRIPTOR in Self relative secdesc format //SelfRelativeSecurityDescriptor + // int rawSecurityDescriptorLength, //available length for secdesc + // IntByReference rawSecurityDescriptorLengthNeeded, //callback needed length for secdesc //Should be computed by dokany + // DokanFileHandle dokanFileHandle); + @NativeName("getFileSecurity") + SelfRelativeSecurityDescriptor getFileSecurity(Path absolutePath, //TODO Return type + String relativePath, + DesiredAccessMask requestedDescriptorInfo, + int availableLength, + DokanyFileHandle dokanyFileHandle); + + // int setFileSecurity( + // WString rawPath, + // int rawSecurityInformation, + // Pointer rawSecurityDescriptor, + // int rawSecurityDescriptorLength, + // DokanFileInfo dokanFileInfo); + @NativeName("setFileSecurity") + void setFileSecurity(Path absolutePath, + String relativePath, + DesiredAccessMask suppliedDescriptorInfo, + SelfRelativeSecurityDescriptor securityDescriptor, + int availableLength, + DokanyFileHandle dokanyFileHandle); + + //TODO fillWin32FindData, findStreams + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java b/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java new file mode 100644 index 00000000..2deb1653 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java @@ -0,0 +1,7 @@ +package dev.dokan.dokan_java.wrappers; + +public class SecurityContext { //Wrapper for WinBase.SECURITY_ATTRIBUTES + + //TODO Hey, I'm a stub! //FIXME + +} \ No newline at end of file From 0b9450c467f05c33694ad802926b83ad55f1a189 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 14 May 2020 20:25:20 +0200 Subject: [PATCH 11/25] Fixed typos/unfinished renaming of classes in EasyDokanyFileSystem --- .../dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java index 7f0e2495..832c4521 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java @@ -21,7 +21,7 @@ public interface EasyDokanyFileSystem { // int rawShareAccess, // int rawCreateDisposition, // int rawCreateOptions, - // DokanFileInfo dokanFileInfo) { //TODO Return type //TODO Incorporate path into DokanFileHandle + // DokanFileInfo dokanFileInfo) { //TODO Return type //TODO Incorporate path into DokanyFileHandle @NativeName("zwCreateFile") void createHandle(Path absolutePath, String relativePath, @@ -142,7 +142,7 @@ void unlockFile(Path absolutePath, // Pointer rawSecurityDescriptor, //Pointer to Buffer. Buffer gets copy of Security Descriptor. SECURITY_DESCRIPTOR in Self relative secdesc format //SelfRelativeSecurityDescriptor // int rawSecurityDescriptorLength, //available length for secdesc // IntByReference rawSecurityDescriptorLengthNeeded, //callback needed length for secdesc //Should be computed by dokany - // DokanFileHandle dokanFileHandle); + // DokanFileInfo dokanFileInfo); @NativeName("getFileSecurity") SelfRelativeSecurityDescriptor getFileSecurity(Path absolutePath, //TODO Return type String relativePath, From 5204c3b0bbf2f680e294c12ae2f895337c463da1 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Fri, 22 May 2020 18:33:32 +0200 Subject: [PATCH 12/25] Unified naming-scheme of wrapper-classes See: e3407477e5214a3d4c765bacd691475d42899fa8 / https://github.com/dokan-dev/dokan-java/issues/37 --- .../java/dev/dokan/dokan_java/wrappers/FindFileInfo.java | 8 ++++---- .../dev/dokan/dokan_java/wrappers/VolumeInformation.java | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java index b58dbf99..b996fef7 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java @@ -1,7 +1,7 @@ package dev.dokan.dokan_java.wrappers; import com.sun.jna.platform.win32.WinBase; -import dev.dokan.dokan_java.DokanyUtils; +import dev.dokan.dokan_java.DokanUtils; import dev.dokan.dokan_java.constants.EnumInteger; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; import dev.dokan.dokan_java.constants.microsoft.MicrosoftReparsePointTag; @@ -125,9 +125,9 @@ public WinBase.WIN32_FIND_DATA toWIN32_FIND_DATA() { int fileSizeLow = (int) (fileSize & 0xffffffffL); return new WinBase.WIN32_FIND_DATA(getFlags(), - DokanyUtils.toFILETIME(getCreationTime()), - DokanyUtils.toFILETIME(getLastAccessTime()), - DokanyUtils.toFILETIME(getLastWriteTime()), + DokanUtils.toFILETIME(getCreationTime()), + DokanUtils.toFILETIME(getLastAccessTime()), + DokanUtils.toFILETIME(getLastWriteTime()), fileSizeHigh, fileSizeLow, getReparsePointTagValueLeniently(), diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java index 440ed5d1..cd63e967 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java @@ -1,12 +1,13 @@ package dev.dokan.dokan_java.wrappers; -import dev.dokan.dokan_java.DokanyOperations; + +import dev.dokan.dokan_java.DokanOperations; import dev.dokan.dokan_java.constants.microsoft.FileSystemFlag; import dev.dokan.dokan_java.structure.EnumIntegerSet; /** * Supplementary class to bundle information of the mounted volume and its filesystem. - *

Mainly used for {@link DokanyOperations#GetVolumeInformation} function to have all needed information at one place.

+ *

Mainly used for {@link DokanOperations#GetVolumeInformation} function to have all needed information at one place.

* TODO: Maybe this can be completely integrated in the DokanyFileSystem class */ public final class VolumeInformation { From 01e50b1582c378f97352edbdff5982b943d256fb Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 23 May 2020 14:23:36 +0200 Subject: [PATCH 13/25] Renamed DokanyFileHandle to DokanFileHandle See: e3407477e5214a3d4c765bacd691475d42899fa8 / https://github.com/dokan-dev/dokan-java/issues/37 --- ...nyFileHandle.java => DokanFileHandle.java} | 4 +- .../wrappers/EasyDokanyFileSystem.java | 50 +++++++++---------- .../wrappers/VolumeInformation.java | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) rename src/main/java/dev/dokan/dokan_java/wrappers/{DokanyFileHandle.java => DokanFileHandle.java} (96%) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java similarity index 96% rename from src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java rename to src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java index facf74b6..0cd9adf9 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DokanyFileHandle.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java @@ -7,7 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger; -public class DokanyFileHandle { //TODO Add Getters?! +public class DokanFileHandle { //TODO Add Getters?! private static final long INVALID_HANDLE = 0L; @@ -17,7 +17,7 @@ public class DokanyFileHandle { //TODO Add Getters?! private int processId; private DokanOptions dokanOpts; //TODO - public DokanyFileHandle(DokanFileInfo nativeInfo) { + public DokanFileHandle(DokanFileInfo nativeInfo) { this.context = nativeInfo.Context; this.dokanContext = nativeInfo.DokanContext; this.processId = nativeInfo.ProcessId; diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java index 832c4521..a4eb97b0 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java @@ -21,7 +21,7 @@ public interface EasyDokanyFileSystem { // int rawShareAccess, // int rawCreateDisposition, // int rawCreateOptions, - // DokanFileInfo dokanFileInfo) { //TODO Return type //TODO Incorporate path into DokanyFileHandle + // DokanFileInfo dokanFileInfo) { //TODO Return type //TODO Incorporate path into DokanFileHandle @NativeName("zwCreateFile") void createHandle(Path absolutePath, String relativePath, @@ -31,47 +31,47 @@ void createHandle(Path absolutePath, EnumIntegerSet shareAccess, CreationDisposition creationDisposition, EnumIntegerSet createOptions, - DokanyFileHandle dokanyFileHandle + DokanFileHandle dokanFileHandle ); //--> zwCreateFile @NativeName("cleanup") - void cleanup(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + void cleanup(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle); @NativeName("closeFile") - void closeHandle(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); //--> CloseFile + void closeHandle(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle); //--> CloseFile @NativeName("readFile") byte[] readFile(Path absolutePath, String relativePath, long offset, int readLength, - DokanyFileHandle dokanyFileHandle); //TODO return -> callback-array? + DokanFileHandle dokanFileHandle); //TODO return -> callback-array? @NativeName("writeFile") - int writeFile(Path absolutePath, String relativePath, byte[] buffer, long offset, DokanyFileHandle dokanyFileHandle); + int writeFile(Path absolutePath, String relativePath, byte[] buffer, long offset, DokanFileHandle dokanFileHandle); @NativeName("flushFileBuffers") - void flush(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + void flush(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle); @NativeName("getFileInformation") - EasyFileInfo getFileInformation(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + EasyFileInfo getFileInformation(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle); @NativeName("findFiles") - Collection findFiles(Path absolutePath, String relativePath, DokanyFileHandle dokanyFileHandle); + Collection findFiles(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle); //TODO --> Collection to callback?! --> default method? @NativeName("findFilesWithPattern") Collection findFilesWithPattern(Path absolutePath, String relativePath, String pattern, //TODO Regex - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); //TODO --> Collection to callback?! @NativeName("setFileAttributes") void setFileAttributes(Path absolutePath, String relativePath, EnumIntegerSet fileAttributes, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("setFileTime") void setFileTime(Path absolutePath, @@ -79,17 +79,17 @@ void setFileTime(Path absolutePath, FileTime creationTime, FileTime lastAccessTime, FileTime lastWriteTime, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("deleteFile") void prepareDeleteFile(Path absolutePath, String relativePath, - DokanyFileHandle dokanyFileHandle); //TODO Rename, return value? + DokanFileHandle dokanFileHandle); //TODO Rename, return value? @NativeName("deleteDirectory") void prepareDeleteDirectory(Path absolutePath, String relativePath, - DokanyFileHandle dokanyFileHandle); //TODO Rename, return value? + DokanFileHandle dokanFileHandle); //TODO Rename, return value? @NativeName("moveFile") void moveFile(Path sourceAbsolutePath, @@ -97,45 +97,45 @@ void moveFile(Path sourceAbsolutePath, Path destinationAbsolutePath, String destinationRelativePath, boolean replaceIfExisting, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("setEndOfFile") void setEndOfFile(Path absolutePath, String relativePath, long fileSize, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("setAllocationSize") void setAllocationSize(Path absolutePath, String relativePath, long allocationSize, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("lockFile") void lockFile(Path absolutePath, String relativePath, long lockOffset, long lockLength, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("unlockFile") void unlockFile(Path absolutePath, String relativePath, long lockOffset, long lockLength, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); @NativeName("getDiskFreeSpace") - DiskSpaceInfo getDiskSpaceInfo(DokanyFileHandle dokanyFileHandle); //TODO Path? + DiskSpaceInfo getDiskSpaceInfo(DokanFileHandle dokanFileHandle); //TODO Path? @NativeName("getVolumeInformation") - VolumeInformation getVolumeInformation(DokanyFileHandle dokanyFileHandle); //TODO Path? + VolumeInformation getVolumeInformation(DokanFileHandle dokanFileHandle); //TODO Path? @NativeName("mounted") - void mounted(DokanyFileHandle dokanyFileHandle); //TODO Path? + void mounted(DokanFileHandle dokanFileHandle); //TODO Path? @NativeName("unmounted") - void unmounted(DokanyFileHandle dokanyFileHandle); //TODO Path? + void unmounted(DokanFileHandle dokanFileHandle); //TODO Path? // int getFileSecurity(WString rawPath, // int /* SecurityInformation */ rawSecurityInformation, //Requested information //DesiredAccessMask OR Similar CLASS OR EnumIntegerSet @@ -148,7 +148,7 @@ SelfRelativeSecurityDescriptor getFileSecurity(Path absolutePath, //TODO Return String relativePath, DesiredAccessMask requestedDescriptorInfo, int availableLength, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); // int setFileSecurity( // WString rawPath, @@ -162,7 +162,7 @@ void setFileSecurity(Path absolutePath, DesiredAccessMask suppliedDescriptorInfo, SelfRelativeSecurityDescriptor securityDescriptor, int availableLength, - DokanyFileHandle dokanyFileHandle); + DokanFileHandle dokanFileHandle); //TODO fillWin32FindData, findStreams diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java index cd63e967..bd1d3e7e 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java @@ -8,7 +8,7 @@ /** * Supplementary class to bundle information of the mounted volume and its filesystem. *

Mainly used for {@link DokanOperations#GetVolumeInformation} function to have all needed information at one place.

- * TODO: Maybe this can be completely integrated in the DokanyFileSystem class + * TODO: Maybe this can be completely integrated in the DokanFileSystem class */ public final class VolumeInformation { private final int maxComponentLength; From ff1d27ed7eaba7e3a428cbc1f0975ad0ec4d72c0 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 23 May 2020 14:30:23 +0200 Subject: [PATCH 14/25] Renamed EasyDokanyFileSystem to EasyDokanFileSystem See: e3407477e5214a3d4c765bacd691475d42899fa8 / https://github.com/dokan-dev/dokan-java/issues/37 --- .../{EasyDokanyFileSystem.java => EasyDokanFileSystem.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/dev/dokan/dokan_java/wrappers/{EasyDokanyFileSystem.java => EasyDokanFileSystem.java} (99%) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java similarity index 99% rename from src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java rename to src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java index a4eb97b0..9d3ec488 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanyFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java @@ -12,7 +12,7 @@ import java.nio.file.attribute.FileTime; import java.util.Collection; -public interface EasyDokanyFileSystem { +public interface EasyDokanFileSystem { //public int zwCreateFile(WString rawPath, // WinBase.SECURITY_ATTRIBUTES securityContext, From 9646e1a6e880dbc868593f129b5a8f1c91098f46 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Sat, 23 May 2020 15:56:03 +0200 Subject: [PATCH 15/25] Renamed SecurityContext to EasyDokanIOSecurityContext Renamed SecurityContext to EasyDokanIOSecurityContext to match the fix in the low-level API (Change from WinBase.SECURITY_ATTRIBUTES to DokanIOSecurityContex as argument of DokanFileSystem#zwCreateFile) --- .../dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java | 4 ++-- .../dokan_java/wrappers/EasyDokanIOSecurityContext.java | 7 +++++++ .../dev/dokan/dokan_java/wrappers/SecurityContext.java | 7 ------- 3 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanIOSecurityContext.java delete mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java index 9d3ec488..28992f30 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java @@ -15,7 +15,7 @@ public interface EasyDokanFileSystem { //public int zwCreateFile(WString rawPath, - // WinBase.SECURITY_ATTRIBUTES securityContext, + // DokanIOSecurityContext securityContext, // int rawDesiredAccess, // int rawFileAttributes, // int rawShareAccess, @@ -25,7 +25,7 @@ public interface EasyDokanFileSystem { @NativeName("zwCreateFile") void createHandle(Path absolutePath, String relativePath, - SecurityContext securityContext, + EasyDokanIOSecurityContext securityContext, DesiredAccessMask desiredAccess, EnumIntegerSet fileAttributes, EnumIntegerSet shareAccess, diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanIOSecurityContext.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanIOSecurityContext.java new file mode 100644 index 00000000..b0fa32f3 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanIOSecurityContext.java @@ -0,0 +1,7 @@ +package dev.dokan.dokan_java.wrappers; + +public class EasyDokanIOSecurityContext { //Wrapper for WinBase.SECURITY_ATTRIBUTES + + //TODO Hey, I'm a stub! //FIXME + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java b/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java deleted file mode 100644 index 2deb1653..00000000 --- a/src/main/java/dev/dokan/dokan_java/wrappers/SecurityContext.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.dokan.dokan_java.wrappers; - -public class SecurityContext { //Wrapper for WinBase.SECURITY_ATTRIBUTES - - //TODO Hey, I'm a stub! //FIXME - -} \ No newline at end of file From 317ad69c84f99bfab74c7a6845028739e07155df Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 28 May 2020 14:49:49 +0200 Subject: [PATCH 16/25] Added overloaded constructor to DokanOptions to allow an int as Options --- .../java/dev/dokan/dokan_java/structure/DokanOptions.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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..4fabaa9e 100644 --- a/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java +++ b/src/main/java/dev/dokan/dokan_java/structure/DokanOptions.java @@ -69,9 +69,13 @@ 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) { + this(mountPoint, threadCount, mountOptions.toInt(), uncName, timeout, allocationUnitSize, sectorSize); + } + + public DokanOptions(final String mountPoint, final short threadCount, final int mountOptions, final String uncName, final long timeout, final long allocationUnitSize, final long sectorSize) { MountPoint = new WString(mountPoint); ThreadCount = threadCount; - Options = mountOptions.toInt(); + Options = mountOptions; if (uncName != null) { UNCName = new WString(uncName); } else { From e600a8f83f72329d95098dd970d976e02843fd33 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 28 May 2020 16:17:28 +0200 Subject: [PATCH 17/25] Added MountInfo-API Added MountInfo-API to wrap the class DokanOptions for the respective field in DokanFileHandle (wrapper for DokanFileInfo). Added Interfaces ROMountInfo and RWMountInfo Added ImmutableMountInfo and MountInfo as implementations This commit is part of my effort to fix dokan-java's issue https://github.com/dokan-dev/dokan-java/issues/32 --- .../mountinfo/ImmutableMountInfo.java | 145 +++++++++++++ .../wrappers/mountinfo/MountInfo.java | 203 ++++++++++++++++++ .../wrappers/mountinfo/ROMountInfo.java | 42 ++++ .../wrappers/mountinfo/RWMountInfo.java | 31 +++ 4 files changed, 421 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java new file mode 100644 index 00000000..39a765ae --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java @@ -0,0 +1,145 @@ +package dev.dokan.dokan_java.wrappers.mountinfo; + + +import com.sun.jna.WString; +import dev.dokan.dokan_java.DokanNativeMethods; +import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.structure.DokanOptions; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + + +public class ImmutableMountInfo implements ROMountInfo { + +// private final long globalContext; + + private final short threadCount; + private final int mountOptions; + private final String mountPoint; + private final String uncName; + private final long timeout; + private final long allocationUnitSize; + private final long sectorSize; + + public ImmutableMountInfo(DokanOptions dokanOptions) { + this.threadCount = dokanOptions.ThreadCount; + this.mountOptions = dokanOptions.Options; +// this.globalContext = dokanOptions.GlobalContext; + this.mountPoint = dokanOptions.MountPoint.toString(); + this.uncName = dokanOptions.UNCName.toString(); + this.timeout = dokanOptions.Timeout; + this.allocationUnitSize = dokanOptions.AllocationUnitSize; + this.sectorSize = dokanOptions.SectorSize; + } + + ImmutableMountInfo(ImmutableMountInfo info) { + this.threadCount = info.threadCount; + this.mountOptions = info.mountOptions; +// this.globalContext = info.globalContext; + this.mountPoint = info.mountPoint; + this.uncName = info.uncName; + this.timeout = info.timeout; + this.allocationUnitSize = info.allocationUnitSize; + this.sectorSize = info.sectorSize; + } + + ImmutableMountInfo(MountInfo info) { + this.threadCount = info.getThreadCount(); + this.mountOptions = info.getFlags(); +// this.globalContext = info.getGlobalContext(); + this.mountPoint = info.getMountPoint(); + this.uncName = info.getUNCName(); + this.timeout = info.getTimeout(); + this.allocationUnitSize = info.getAllocationUnitSize(); + this.sectorSize = info.getSectorSize(); + } + + @Override + public short getDokanVersion() { + return DokanNativeMethods.getMinimumRequiredDokanVersion(); + } + + @Override + public short getThreadCount() { + return this.threadCount; + } + + @Override + public EnumIntegerSet getMountOptions() { + return MountOption.fromInt(this.mountOptions); + } + + @Override + public int getFlags() { + return this.mountOptions; + } + + @Override + public boolean getFlag(MountOption flag) { + return (this.mountOptions & flag.getMask()) != 0; + } + +// @Override +// public long getGlobalContext() { +// return this.globalContext; +// } + + @Override + public String getMountPoint() { + return this.mountPoint; + } + + @Override + public String getUNCName() { + return this.uncName; + } + + @Override + public long getTimeout() { + return this.timeout; + } + + @Override + public long getAllocationUnitSize() { + return this.allocationUnitSize; + } + + @Override + public long getSectorSize() { + return this.sectorSize; + } + + @Override + public boolean isMutable() { + return false; + } + + @Override + public ROMountInfo immutableCopy() { + return new ImmutableMountInfo(this); + } + + @Override + public RWMountInfo mutableCopy() { + return new MountInfo(this); + } + + @Override + public DokanOptions nativeCopy() { + DokanOptions options = new DokanOptions(this.mountPoint, this.threadCount, this.mountOptions, this.uncName, this.timeout, this.allocationUnitSize, this.sectorSize); +// options.GlobalContext = this.globalContext; + + return options; + } + + @Override + public void nativeCopy(DokanOptions options) { + options.ThreadCount = this.threadCount; + options.Options = this.mountOptions; +// options.GlobalContext = this.globalContext; + options.MountPoint = new WString(this.mountPoint); + options.UNCName = new WString(this.uncName); + options.Timeout = this.timeout; + options.AllocationUnitSize = this.allocationUnitSize; + options.SectorSize = this.sectorSize; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java new file mode 100644 index 00000000..77207214 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java @@ -0,0 +1,203 @@ +package dev.dokan.dokan_java.wrappers.mountinfo; + + +import com.sun.jna.WString; +import dev.dokan.dokan_java.DokanNativeMethods; +import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.structure.DokanOptions; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + + +public class MountInfo implements RWMountInfo { + +// private long globalContext; + + private short threadCount; + private int mountOptions; + private String mountPoint; + private String uncName; + private long timeout; + private long allocationUnitSize; + private long sectorSize; + + public MountInfo(DokanOptions dokanOptions) { + this.threadCount = dokanOptions.ThreadCount; + this.mountOptions = dokanOptions.Options; +// this.globalContext = dokanOptions.GlobalContext; + this.mountPoint = dokanOptions.MountPoint.toString(); + this.uncName = dokanOptions.UNCName.toString(); + this.timeout = dokanOptions.Timeout; + this.allocationUnitSize = dokanOptions.AllocationUnitSize; + this.sectorSize = dokanOptions.SectorSize; + } + + MountInfo(MountInfo info) { + this.threadCount = info.threadCount; + this.mountOptions = info.mountOptions; +// this.globalContext = info.globalContext; + this.mountPoint = info.mountPoint; + this.uncName = info.uncName; + this.timeout = info.timeout; + this.allocationUnitSize = info.allocationUnitSize; + this.sectorSize = info.sectorSize; + } + + MountInfo(ImmutableMountInfo info) { + this.threadCount = info.getThreadCount(); + this.mountOptions = info.getFlags(); +// this.globalContext = info.getGlobalContext(); + this.mountPoint = info.getMountPoint(); + this.uncName = info.getUNCName(); + this.timeout = info.getTimeout(); + this.allocationUnitSize = info.getAllocationUnitSize(); + this.sectorSize = info.getSectorSize(); + } + + @Override + public short getDokanVersion() { + return DokanNativeMethods.getMinimumRequiredDokanVersion(); + } + + @Override + public short getThreadCount() { + return this.threadCount; + } + + @Override + public void setThreadCount(short threadCount) { + this.threadCount = threadCount; + } + + @Override + public EnumIntegerSet getMountOptions() { + return MountOption.fromInt(this.mountOptions); + } + + @Override + public void setMountOptions(EnumIntegerSet mountOptions) { + this.mountOptions = mountOptions.toInt(); + } + + @Override + public int getFlags() { + return this.mountOptions; + } + + @Override + public void setFlags(int flags) { + this.mountOptions = flags; + } + + @Override + public boolean getFlag(MountOption flag) { + return (this.mountOptions & flag.getMask()) != 0; + } + + @Override + public boolean setFlag(MountOption flag) { + return updateFlag(flag, true); + } + + @Override + public boolean unsetFlag(MountOption flag) { + return updateFlag(flag, false); + } + + @Override + public boolean updateFlag(MountOption flag, boolean value) { + boolean prev = getFlag(flag); + this.mountOptions &= value ? flag.getMask() : ~flag.getMask(); + + return prev; + } + +// @Override +// public long getGlobalContext() { +// return this.globalContext; +// } + + @Override + public String getMountPoint() { + return this.mountPoint; + } + + @Override + public void setMountPoint(String mountPoint) { + this.mountPoint = mountPoint; + } + + @Override + public String getUNCName() { + return this.uncName; + } + + @Override + public void setUNCName(String uncName) { + this.uncName = uncName; + } + + @Override + public long getTimeout() { + return this.timeout; + } + + @Override + public void setTimeout(long timeout) { + this.timeout = timeout; + } + + @Override + public long getAllocationUnitSize() { + return this.allocationUnitSize; + } + + @Override + public void setAllocationUnitSize(long allocationUnitSize) { + this.allocationUnitSize = allocationUnitSize; + } + + @Override + public long getSectorSize() { + return this.sectorSize; + } + + @Override + public void setSectorSize(long sectorSize) { + this.sectorSize = sectorSize; + } + + @Override + public boolean isMutable() { + return true; + } + + @Override + public ROMountInfo immutableCopy() { + return new ImmutableMountInfo(this); + } + + @Override + public RWMountInfo mutableCopy() { + return new MountInfo(this); + } + + @Override + public DokanOptions nativeCopy() { + DokanOptions options = new DokanOptions(this.mountPoint, this.threadCount, this.mountOptions, this.uncName, this.timeout, this.allocationUnitSize, this.sectorSize); +// options.GlobalContext = this.globalContext; + + return options; + } + + @Override + public void nativeCopy(DokanOptions options) { + options.ThreadCount = this.threadCount; + options.Options = this.mountOptions; +// options.GlobalContext = this.globalContext; + options.MountPoint = new WString(this.mountPoint); + options.UNCName = new WString(this.uncName); + options.Timeout = this.timeout; + options.AllocationUnitSize = this.allocationUnitSize; + options.SectorSize = this.sectorSize; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java new file mode 100644 index 00000000..3323e266 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java @@ -0,0 +1,42 @@ +package dev.dokan.dokan_java.wrappers.mountinfo; + + +import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.structure.DokanOptions; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + + +public interface ROMountInfo { + + short getDokanVersion(); + + short getThreadCount(); + + EnumIntegerSet getMountOptions(); + + int getFlags(); + + boolean getFlag(MountOption flag); + +// long getGlobalContext(); + + String getMountPoint(); + + String getUNCName(); + + long getTimeout(); + + long getAllocationUnitSize(); + + long getSectorSize(); + + boolean isMutable(); + + ROMountInfo immutableCopy(); + + RWMountInfo mutableCopy(); + + DokanOptions nativeCopy(); + + void nativeCopy(DokanOptions options); +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java new file mode 100644 index 00000000..aee5093c --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java @@ -0,0 +1,31 @@ +package dev.dokan.dokan_java.wrappers.mountinfo; + + +import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.structure.EnumIntegerSet; + + +public interface RWMountInfo extends ROMountInfo { + + void setThreadCount(short threadCount); + + void setMountOptions(EnumIntegerSet mountOptions); + + void setFlags(int flags); + + boolean setFlag(MountOption flag); + + boolean unsetFlag(MountOption flag); + + boolean updateFlag(MountOption flag, boolean value); + + void setMountPoint(String mountPoint); + + void setUNCName(String uncName); + + void setTimeout(long timeout); + + void setAllocationUnitSize(long allocationUnitSize); + + void setSectorSize(long sectorSize); +} \ No newline at end of file From 98e1497c95b7a40cfbb025d0450afe3d5fd07c57 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 28 May 2020 18:23:48 +0200 Subject: [PATCH 18/25] Added last basic API-Classes Added ForwardingFileSystem as delegator for method-calls between EasyDokanFileSystem-implementations and DokanFileSystem-API Added EasyDokanFileSystemStub as stub for implementations of EasyDokanFileSystem (similiar to DokanFileSystemStub) Added AbstractEasyDokanFileSystem as base class for implementations of EasyDokanFileSystem (similiar to AbstractDokanFileSystem) This commit is part of my effort to fix dokan-java's issue https://github.com/dokan-dev/dokan-java/issues/32 --- .../wrappers/AbstractEasyDokanFileSystem.java | 69 +++++ .../wrappers/EasyDokanFileSystemStub.java | 217 ++++++++++++++++ .../wrappers/ForwardingFileSystem.java | 241 ++++++++++++++++++ 3 files changed, 527 insertions(+) create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java new file mode 100644 index 00000000..352f2173 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractEasyDokanFileSystem.java @@ -0,0 +1,69 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.NativeName; +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.NotImplemented; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public abstract class AbstractEasyDokanFileSystem implements EasyDokanFileSystem { + + private final Set notImplementedMethods; + private final ForwardingFileSystem lowLevelFS; + + public AbstractEasyDokanFileSystem(FileSystemInformation fileSystemInformation) { + this.notImplementedMethods = Arrays.stream(getClass().getMethods()) + .filter(method -> method.getAnnotation(NotImplemented.class) != null) + .map((method) -> getNativeName(method)) + .collect(Collectors.toSet()); + + this.lowLevelFS = new ForwardingFileSystem(fileSystemInformation, this.notImplementedMethods, this); + } + + private String getNativeName(Method method) { + Method annotated = getAnnotatedMethod(NativeName.class, method); + + if(annotated == null) { + return method.getName(); + } + return annotated.getAnnotation(NativeName.class).value(); + } + + private Method getAnnotatedMethod(Class annotation, Method method) { + return getAnnotatedMethod(annotation, method.getDeclaringClass(), method.getName(), method.getParameterTypes()); + } + + private Method getAnnotatedMethod(Class annotation, + Class inClass, + String methodName, + Class... parameterTypes) { + + Method result; + try { + result = inClass.getMethod(methodName, parameterTypes); + } catch(NoSuchMethodException e) { + return null; + } + + if(result.isAnnotationPresent(annotation)) { + return result; + } + + Class superClass = inClass.getSuperclass(); + if(superClass != null) { + result = getAnnotatedMethod(annotation, superClass, methodName, parameterTypes); + } + + if(result != null) { + return result; + } + + return Arrays.stream(inClass.getInterfaces()) + .map((cInterface) -> getAnnotatedMethod(annotation, cInterface, methodName, parameterTypes)) + .findFirst().orElse(null); + } +} diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java new file mode 100644 index 00000000..17587150 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java @@ -0,0 +1,217 @@ +package dev.dokan.dokan_java.wrappers; + +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.NotImplemented; +import dev.dokan.dokan_java.constants.microsoft.CreateOption; +import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; +import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.constants.microsoft.FileShareAccess; +import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.structure.filesecurity.SelfRelativeSecurityDescriptor; + +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.util.Collection; + +public class EasyDokanFileSystemStub extends AbstractEasyDokanFileSystem { + + public EasyDokanFileSystemStub(FileSystemInformation fileSystemInformation) { + super(fileSystemInformation); + } + + @NotImplemented + @Override + public void createHandle(Path absolutePath, + String relativePath, + EasyDokanIOSecurityContext securityContext, + DesiredAccessMask desiredAccess, + EnumIntegerSet fileAttributes, + EnumIntegerSet shareAccess, + CreationDisposition creationDisposition, + EnumIntegerSet createOptions, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void cleanup(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void closeHandle(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public byte[] readFile(Path absolutePath, + String relativePath, + long offset, + int readLength, + DokanFileHandle dokanFileHandle) { + return new byte[0]; + } + + @NotImplemented + @Override + public int writeFile(Path absolutePath, + String relativePath, + byte[] buffer, + long offset, + DokanFileHandle dokanFileHandle) { + return 0; + } + + @NotImplemented + @Override + public void flush(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public EasyFileInfo getFileInformation(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public Collection findFiles(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public Collection findFilesWithPattern(Path absolutePath, + String relativePath, + String pattern, + DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void setFileAttributes(Path absolutePath, + String relativePath, + EnumIntegerSet fileAttributes, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setFileTime(Path absolutePath, + String relativePath, + FileTime creationTime, + FileTime lastAccessTime, + FileTime lastWriteTime, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void prepareDeleteFile(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void prepareDeleteDirectory(Path absolutePath, String relativePath, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void moveFile(Path sourceAbsolutePath, + String sourceRelativePath, + Path destinationAbsolutePath, + String destinationRelativePath, + boolean replaceIfExisting, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setEndOfFile(Path absolutePath, String relativePath, long fileSize, DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void setAllocationSize(Path absolutePath, + String relativePath, + long allocationSize, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void lockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void unlockFile(Path absolutePath, + String relativePath, + long lockOffset, + long lockLength, + DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public DiskSpaceInfo getDiskSpaceInfo(DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public VolumeInformation getVolumeInformation(DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void mounted(DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public void unmounted(DokanFileHandle dokanFileHandle) { + + } + + @NotImplemented + @Override + public SelfRelativeSecurityDescriptor getFileSecurity(Path absolutePath, + String relativePath, + DesiredAccessMask requestedDescriptorInfo, + int availableLength, + DokanFileHandle dokanFileHandle) { + return null; + } + + @NotImplemented + @Override + public void setFileSecurity(Path absolutePath, + String relativePath, + DesiredAccessMask suppliedDescriptorInfo, + SelfRelativeSecurityDescriptor securityDescriptor, + int availableLength, + DokanFileHandle dokanFileHandle) { + + } +} diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java new file mode 100644 index 00000000..2cbcb75b --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/ForwardingFileSystem.java @@ -0,0 +1,241 @@ +package dev.dokan.dokan_java.wrappers; + + +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinBase; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.LongByReference; +import dev.dokan.dokan_java.AbstractDokanFileSystem; +import dev.dokan.dokan_java.DokanException; +import dev.dokan.dokan_java.DokanOperations; +import dev.dokan.dokan_java.FileSystemInformation; +import dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes; +import dev.dokan.dokan_java.structure.ByHandleFileInformation; +import dev.dokan.dokan_java.structure.DokanFileInfo; +import dev.dokan.dokan_java.structure.DokanIOSecurityContext; + +import java.nio.file.Path; +import java.util.Set; + + +public class ForwardingFileSystem extends AbstractDokanFileSystem { + + private final Set notImplementedMethods; + private final AbstractEasyDokanFileSystem creator; + + public ForwardingFileSystem(FileSystemInformation fileSystemInformation, Set notImplementedMethods, AbstractEasyDokanFileSystem target) { + super(fileSystemInformation); + this.notImplementedMethods = notImplementedMethods; + this.creator = target; + } + + @Override + public boolean isImplemented(String funcName) { + return !this.notImplementedMethods.contains(funcName); + } + + + @Override + public int zwCreateFile(WString rawPath, DokanIOSecurityContext securityContext, int rawDesiredAccess, int rawFileAttributes, int rawShareAccess, int rawCreateDisposition, int rawCreateOptions, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public void cleanup(WString rawPath, DokanFileInfo dokanFileInfo) { + + } + + @Override + public void closeFile(WString rawPath, DokanFileInfo dokanFileInfo) { + + } + + @Override + public int readFile(WString rawPath, + Pointer rawBuffer, + int rawBufferLength, + IntByReference rawReadLength, + long rawOffset, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int writeFile(WString rawPath, + Pointer rawBuffer, + int rawNumberOfBytesToWrite, + IntByReference rawNumberOfBytesWritten, + long rawOffset, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int flushFileBuffers(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getFileInformation(WString fileName, + ByHandleFileInformation handleFileInfo, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int findFiles(WString rawPath, + DokanOperations.FillWin32FindData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int findFilesWithPattern(WString fileName, + WString searchPattern, + DokanOperations.FillWin32FindData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileAttributes(WString rawPath, int rawAttributes, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileTime(WString rawPath, + WinBase.FILETIME rawCreationTime, + WinBase.FILETIME rawLastAccessTime, + WinBase.FILETIME rawLastWriteTime, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int deleteFile(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int deleteDirectory(WString rawPath, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int moveFile(WString rawPath, + WString rawNewFileName, + boolean rawReplaceIfExisting, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setEndOfFile(WString rawPath, long rawByteOffset, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setAllocationSize(WString rawPath, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int lockFile(WString rawPath, long rawByteOffset, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int unlockFile(WString rawPath, long rawByteOffset, long rawLength, DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getDiskFreeSpace(LongByReference freeBytesAvailable, + LongByReference totalNumberOfBytes, + LongByReference totalNumberOfFreeBytes, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getVolumeInformation(Pointer rawVolumeNameBuffer, + int rawVolumeNameSize, + IntByReference rawVolumeSerialNumber, + IntByReference rawMaximumComponentLength, + IntByReference rawFileSystemFlags, + Pointer rawFileSystemNameBuffer, + int rawFileSystemNameSize, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int mounted(DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int unmounted(DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int getFileSecurity(WString rawPath, + int rawSecurityInformation, + Pointer rawSecurityDescriptor, + int rawSecurityDescriptorLength, + IntByReference rawSecurityDescriptorLengthNeeded, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public int setFileSecurity(WString rawPath, + int rawSecurityInformation, + Pointer rawSecurityDescriptor, + int rawSecurityDescriptorLength, + DokanFileInfo dokanFileInfo) { + return 0; + } + + @Override + public void fillWin32FindData(WinBase.WIN32_FIND_DATA rawFillFindData, DokanFileInfo dokanFileInfo) { + + } + + @Override + public int findStreams(WString rawPath, + DokanOperations.FillWin32FindStreamData rawFillFindData, + DokanFileInfo dokanFileInfo) { + return 0; + } + + private int handleException(DokanException exc) { //TODO Reformat to allow any kind of exception + if (exc == null) { + return Win32ErrorCodes.ERROR_GEN_FAILURE; + } + + if (exc.getErrorCode() == Integer.MIN_VALUE) { + //TODO + } + //TODO Log + return exc.getErrorCode(); + } + + private String resolveRelativePath(WString path) { + return resolveRelativePath(path.toString()); + } + + private String resolveRelativePath(String path) { + return path; + } + + private Path resolveAbsolutePath(WString path) { + return resolveAbsolutePath(path.toString()); + } + + private Path resolveAbsolutePath(String path) { + return null; //TODO Implement + } +} \ No newline at end of file From bbc2004b20b003546748d4852353dde9ae316642 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Tue, 2 Jun 2020 23:07:05 +0200 Subject: [PATCH 19/25] Fixed issues that arose from merging Fixed wrong implements-statements Added missing convenience methods Renamed parameters/fields Replaced outdated constructors Replaced outdated methods --- .../constants/dokany/DokanFileInfoFlag.java | 20 +++++++++----- .../constants/microsoft/FileShareAccess.java | 20 +++++++++----- .../microsoft/MicrosoftReparsePointTag.java | 16 +++++++----- .../dokan_java/wrappers/AbstractFileInfo.java | 16 ++++++------ .../wrappers/DesiredAccessMask.java | 26 +++++++++---------- .../dokan_java/wrappers/DokanFileHandle.java | 16 ++++++------ .../wrappers/EasyDokanFileSystem.java | 12 ++++----- .../wrappers/EasyDokanFileSystemStub.java | 10 +++---- .../dokan_java/wrappers/EasyFileInfo.java | 6 ++--- .../dokan_java/wrappers/FindFileInfo.java | 10 +++---- .../wrappers/VolumeInformation.java | 10 +++---- .../mountinfo/ImmutableMountInfo.java | 8 +++--- .../wrappers/mountinfo/MountInfo.java | 14 +++++----- .../wrappers/mountinfo/ROMountInfo.java | 4 +-- .../wrappers/mountinfo/RWMountInfo.java | 4 +-- 15 files changed, 104 insertions(+), 88 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java index 7e5715d8..ccca428e 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/dokany/DokanFileInfoFlag.java @@ -1,8 +1,10 @@ package dev.dokan.dokan_java.constants.dokany; -import dev.dokan.dokan_java.constants.EnumInteger; -public enum DokanFileInfoFlag implements EnumInteger { +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; + +public enum DokanFileInfoFlag implements MaskValueEnum { DELETE_ON_CLOSE(1), IS_DIRECTORY(2), @@ -11,14 +13,18 @@ public enum DokanFileInfoFlag implements EnumInteger { SYNCHRONOUS_IO(16), WRITE_TO_END_OF_FILE(32); - private final int mask; + private final int maskingValue; + + DokanFileInfoFlag(int maskingValue) { + this.maskingValue = maskingValue; + } - DokanFileInfoFlag(int mask) { - this.mask = mask; + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } @Override - public int getMask() { - return this.mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java index 3efc96b3..d9f4d487 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/FileShareAccess.java @@ -1,21 +1,27 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; -public enum FileShareAccess implements EnumInteger { +import dev.dokan.dokan_java.masking.MaskValueEnum; +import dev.dokan.dokan_java.masking.MaskValueSet; + +public enum FileShareAccess implements MaskValueEnum { FILE_SHARE_READ(1), FILE_SHARE_WRITE(2), FILE_SHARE_DELETE(4); - private final int mask; + private final int maskingValue; + + FileShareAccess(int maskingValue) { + this.maskingValue = maskingValue; + } - FileShareAccess(int mask) { - this.mask = mask; + public static MaskValueSet maskValueSet(final int mask) { + return MaskValueSet.maskValueSet(mask, values()); } @Override - public int getMask() { - return this.mask; + public int intValue() { + return this.maskingValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java index 808650a4..1a52b7d0 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java @@ -1,6 +1,6 @@ package dev.dokan.dokan_java.constants.microsoft; -import dev.dokan.dokan_java.constants.EnumInteger; +import dev.dokan.dokan_java.masking.EnumInteger; public enum MicrosoftReparsePointTag implements EnumInteger { @@ -16,14 +16,18 @@ public enum MicrosoftReparsePointTag implements EnumInteger { IO_REPARSE_TAG_SYMLINK(0xA000000C), IO_REPARSE_TAG_WIM(0x80000008); - private final int mask; + private final int intValue; - MicrosoftReparsePointTag(int mask) { - this.mask = mask; + MicrosoftReparsePointTag(int intValue) { + this.intValue = intValue; + } + + public static MicrosoftReparsePointTag fromInt(final int value) { + return EnumInteger.enumFromInt(value, values()); } @Override - public int getMask() { - return this.mask; + public int intValue() { + return this.intValue; } } diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java index d4535977..3cb178d1 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/AbstractFileInfo.java @@ -2,7 +2,7 @@ import dev.dokan.dokan_java.constants.dokan_java.DefaultFileTimePolicy; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.nio.file.attribute.FileTime; import java.util.concurrent.atomic.AtomicInteger; @@ -25,8 +25,8 @@ public class AbstractFileInfo { private DefaultFileTimePolicy fileTimePolicy = DefaultFileTimePolicy.INHERIT_ELSE_1970; private long fileSize; - public AbstractFileInfo(EnumIntegerSet attributes) { - this(attributes.isEmpty() ? FileAttribute.NORMAL.getMask() : attributes.toInt()); + public AbstractFileInfo(MaskValueSet attributes) { + this(attributes.isEmpty() ? FileAttribute.NORMAL.maskingValue() : attributes.intValue()); } public AbstractFileInfo(int attributes) { @@ -41,12 +41,12 @@ public void setFlags(int flags) { this.fileAttributes.set(flags); } - public EnumIntegerSet getFileAttributes() { - return EnumIntegerSet.enumSetFromInt(this.fileAttributes.get(), FileAttribute.values()); + public MaskValueSet getFileAttributes() { + return MaskValueSet.maskValueSet(this.fileAttributes.get(), FileAttribute.values()); } public boolean getFlag(FileAttribute flag) { - return (this.fileAttributes.get() & flag.getMask()) != 0; + return (this.fileAttributes.get() & flag.maskingValue()) != 0; } public boolean setFlag(FileAttribute flag) { @@ -58,8 +58,8 @@ public boolean unsetFlag(FileAttribute flag) { } public boolean updateFlag(FileAttribute flag, boolean value) { - int prev = this.fileAttributes.getAndUpdate(current -> current & (value ? flag.getMask() : ~flag.getMask())); - return (prev & flag.getMask()) != 0; + int prev = this.fileAttributes.getAndUpdate(current -> current & (value ? flag.maskingValue() : ~flag.maskingValue())); + return (prev & flag.maskingValue()) != 0; } public void setTimes(long creationTime, long lastAccessTime, long lastWriteTime) { diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java index 83b54eee..fa0778e0 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -4,7 +4,7 @@ import dev.dokan.dokan_java.constants.microsoft.DirectoryAccessMask; import dev.dokan.dokan_java.constants.microsoft.FileAccessMask; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.util.concurrent.atomic.AtomicInteger; @@ -14,10 +14,10 @@ public class DesiredAccessMask { private final AtomicInteger accessMask; public DesiredAccessMask(int rawAccessMask, int rawFileAttributes) { - this(rawAccessMask, (rawFileAttributes & FileAttribute.DIRECTORY.getMask()) != 0); + this(rawAccessMask, (rawFileAttributes & FileAttribute.DIRECTORY.maskingValue()) != 0); } - public DesiredAccessMask(int rawAccessMask, EnumIntegerSet fileAttributes) { + public DesiredAccessMask(int rawAccessMask, MaskValueSet fileAttributes) { this(rawAccessMask, fileAttributes.contains(FileAttribute.DIRECTORY)); } @@ -28,12 +28,12 @@ public DesiredAccessMask(int rawAccessMask, boolean isDirectory) { this.accessMask = new AtomicInteger(rawAccessMask); } - public EnumIntegerSet getBasicRights() { - return EnumIntegerSet.enumSetFromInt(this.accessMask.get(), AccessMask.values()); + public MaskValueSet getBasicRights() { + return MaskValueSet.maskValueSet(this.accessMask.get(), AccessMask.values()); } - public EnumIntegerSet getSpecificRights() { - return EnumIntegerSet.enumSetFromInt(this.accessMask.get(), FileAccessMask.values()); + public MaskValueSet getSpecificRights() { + return MaskValueSet.maskValueSet(this.accessMask.get(), FileAccessMask.values()); } public boolean isDirectory() { @@ -49,11 +49,11 @@ public void setAccessMask(int accessMask) { } public boolean getFlag(AccessMask flag) { - return getFlag(flag.getMask()); + return getFlag(flag.maskingValue()); } public boolean getFlag(FileAccessMask flag) { - return getFlag(flag.getMask()); + return getFlag(flag.maskingValue()); } public boolean getFlag(DirectoryAccessMask flag) { @@ -64,7 +64,7 @@ public boolean getFlag(DirectoryAccessMask flag) { } public boolean silentGetFlag(DirectoryAccessMask flag) { - return getFlag(flag.getMask()); + return getFlag(flag.maskingValue()); } public boolean getFlag(int flag) { @@ -80,7 +80,7 @@ public boolean unsetFlag(AccessMask flag) { } public boolean updateFlag(AccessMask flag, boolean value) { - return updateFlag(flag.getMask(), value); + return updateFlag(flag.maskingValue(), value); } public boolean setFlag(FileAccessMask flag) { @@ -92,7 +92,7 @@ public boolean unsetFlag(FileAccessMask flag) { } public boolean updateFlag(FileAccessMask flag, boolean value) { - return updateFlag(flag.getMask(), value); + return updateFlag(flag.maskingValue(), value); } public boolean setFlag(DirectoryAccessMask flag) { @@ -125,7 +125,7 @@ public boolean silentUnsetFlag(DirectoryAccessMask flag) { } public boolean silentUpdateFlag(DirectoryAccessMask flag, boolean value) { - return updateFlag(flag.getMask(), value); + return updateFlag(flag.maskingValue(), value); } public boolean updateFlag(int flag, boolean value) { diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java index 0cd9adf9..1e64a9f7 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java @@ -1,9 +1,9 @@ package dev.dokan.dokan_java.wrappers; import dev.dokan.dokan_java.constants.dokany.DokanFileInfoFlag; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.DokanFileInfo; import dev.dokan.dokan_java.structure.DokanOptions; -import dev.dokan.dokan_java.structure.EnumIntegerSet; import java.util.concurrent.atomic.AtomicInteger; @@ -23,7 +23,7 @@ public DokanFileHandle(DokanFileInfo nativeInfo) { this.processId = nativeInfo.ProcessId; this.dokanOpts = nativeInfo.DokanOpts; //TODO Copy/Different link? - EnumIntegerSet flagSet = new EnumIntegerSet<>(DokanFileInfoFlag.class); + MaskValueSet flagSet = MaskValueSet.emptySet(DokanFileInfoFlag.class); if(nativeInfo.deleteOnClose()) { flagSet.add(DokanFileInfoFlag.DELETE_ON_CLOSE); } @@ -42,11 +42,11 @@ public DokanFileHandle(DokanFileInfo nativeInfo) { if(nativeInfo.writeToEndOfFile()) { flagSet.add(DokanFileInfoFlag.WRITE_TO_END_OF_FILE); } - this.flags = new AtomicInteger(flagSet.toInt()); + this.flags = new AtomicInteger(flagSet.intValue()); } - public EnumIntegerSet getFileInfo() { - return EnumIntegerSet.enumSetFromInt(this.flags.get(), DokanFileInfoFlag.values()); + public MaskValueSet getFileInfo() { + return MaskValueSet.maskValueSet(this.flags.get(), DokanFileInfoFlag.values()); } public int getFlags() { @@ -58,7 +58,7 @@ public void setFlags(int flags) { } public boolean getFlag(DokanFileInfoFlag flag) { - return (this.flags.get() & flag.getMask()) != 0; + return (this.flags.get() & flag.maskingValue()) != 0; } public boolean setFlag(DokanFileInfoFlag flag) { @@ -70,8 +70,8 @@ public boolean unsetFlag(DokanFileInfoFlag flag) { } public boolean updateFlag(DokanFileInfoFlag flag, boolean value) { - int prev = this.flags.getAndUpdate(current -> current & (value ? flag.getMask() : ~flag.getMask())); - return (prev & flag.getMask()) != 0; + int prev = this.flags.getAndUpdate(current -> current & (value ? flag.maskingValue() : ~flag.maskingValue())); + return (prev & flag.maskingValue()) != 0; } public long getContext() { diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java index 28992f30..200e85a1 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystem.java @@ -5,7 +5,7 @@ import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; import dev.dokan.dokan_java.constants.microsoft.FileShareAccess; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.filesecurity.SelfRelativeSecurityDescriptor; import java.nio.file.Path; @@ -27,10 +27,10 @@ void createHandle(Path absolutePath, String relativePath, EasyDokanIOSecurityContext securityContext, DesiredAccessMask desiredAccess, - EnumIntegerSet fileAttributes, - EnumIntegerSet shareAccess, + MaskValueSet fileAttributes, + MaskValueSet shareAccess, CreationDisposition creationDisposition, - EnumIntegerSet createOptions, + MaskValueSet createOptions, DokanFileHandle dokanFileHandle ); //--> zwCreateFile @@ -70,7 +70,7 @@ Collection findFilesWithPattern(Path absolutePath, @NativeName("setFileAttributes") void setFileAttributes(Path absolutePath, String relativePath, - EnumIntegerSet fileAttributes, + MaskValueSet fileAttributes, DokanFileHandle dokanFileHandle); @NativeName("setFileTime") @@ -138,7 +138,7 @@ void unlockFile(Path absolutePath, void unmounted(DokanFileHandle dokanFileHandle); //TODO Path? // int getFileSecurity(WString rawPath, - // int /* SecurityInformation */ rawSecurityInformation, //Requested information //DesiredAccessMask OR Similar CLASS OR EnumIntegerSet + // int /* SecurityInformation */ rawSecurityInformation, //Requested information //DesiredAccessMask OR Similar CLASS OR MaskValueSet // Pointer rawSecurityDescriptor, //Pointer to Buffer. Buffer gets copy of Security Descriptor. SECURITY_DESCRIPTOR in Self relative secdesc format //SelfRelativeSecurityDescriptor // int rawSecurityDescriptorLength, //available length for secdesc // IntByReference rawSecurityDescriptorLengthNeeded, //callback needed length for secdesc //Should be computed by dokany diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java index 17587150..c61c0bdb 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyDokanFileSystemStub.java @@ -6,7 +6,7 @@ import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; import dev.dokan.dokan_java.constants.microsoft.FileShareAccess; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.filesecurity.SelfRelativeSecurityDescriptor; import java.nio.file.Path; @@ -25,10 +25,10 @@ public void createHandle(Path absolutePath, String relativePath, EasyDokanIOSecurityContext securityContext, DesiredAccessMask desiredAccess, - EnumIntegerSet fileAttributes, - EnumIntegerSet shareAccess, + MaskValueSet fileAttributes, + MaskValueSet shareAccess, CreationDisposition creationDisposition, - EnumIntegerSet createOptions, + MaskValueSet createOptions, DokanFileHandle dokanFileHandle) { } @@ -96,7 +96,7 @@ public Collection findFilesWithPattern(Path absolutePath, @Override public void setFileAttributes(Path absolutePath, String relativePath, - EnumIntegerSet fileAttributes, + MaskValueSet fileAttributes, DokanFileHandle dokanFileHandle) { } diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java index 1a31a54e..e7b30d1c 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/EasyFileInfo.java @@ -1,8 +1,8 @@ package dev.dokan.dokan_java.wrappers; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.ByHandleFileInformation; -import dev.dokan.dokan_java.structure.EnumIntegerSet; import java.nio.file.Path; @@ -15,10 +15,10 @@ public class EasyFileInfo extends AbstractFileInfo { private int numberOfLinks; public EasyFileInfo(Path path) { - this(path, FileAttribute.NORMAL.getMask()); + this(path, FileAttribute.NORMAL.maskingValue()); } - public EasyFileInfo(Path path, EnumIntegerSet attributes) { + public EasyFileInfo(Path path, MaskValueSet attributes) { super(attributes); this.path = path; } diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java index b996fef7..ca99ff1b 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java @@ -2,10 +2,10 @@ import com.sun.jna.platform.win32.WinBase; import dev.dokan.dokan_java.DokanUtils; -import dev.dokan.dokan_java.constants.EnumInteger; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; import dev.dokan.dokan_java.constants.microsoft.MicrosoftReparsePointTag; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.EnumInteger; +import dev.dokan.dokan_java.masking.MaskValueSet; import java.util.Objects; import java.util.function.Function; @@ -23,7 +23,7 @@ public class FindFileInfo extends AbstractFileInfo { private String fileName; private String alternativeName; - public FindFileInfo(EnumIntegerSet attributes) { + public FindFileInfo(MaskValueSet attributes) { super(attributes); } @@ -53,12 +53,12 @@ public void setMSReparsePointTag(MicrosoftReparsePointTag tag) { setReparsePointTag(tag); } - public T getReparsePointTag(T[] possibleValues) { + public & EnumInteger> T getReparsePointTag(T[] possibleValues) { return EnumInteger.enumFromInt(getReparsePointTagValue(), possibleValues); } public void setReparsePointTag(T tag) { - setReparsePointTagValue(tag.getMask()); + setReparsePointTagValue(tag.intValue()); } public > T getReparsePointTag(Function parser) { diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java index bd1d3e7e..c5af5094 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/VolumeInformation.java @@ -3,7 +3,7 @@ import dev.dokan.dokan_java.DokanOperations; 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 mounted volume and its filesystem. @@ -15,13 +15,13 @@ public final class VolumeInformation { private final String name; private final int serialNumber; private final String fileSystemName; - private final EnumIntegerSet fileSystemFeatures; + private final MaskValueSet fileSystemFeatures; public static final int DEFAULT_MAX_COMPONENT_LENGTH = 256; public static final int DEFAULT_SERIAL_NUMBER = 305419896; public static final String DEFAULT_VOLUME_NAME = "VOLUME1"; public static final String DEFAULT_FS_NAME = "DOKANY"; - public static final EnumIntegerSet DEFAULT_FS_FEATURES = new EnumIntegerSet<>(FileSystemFlag.class); + public static final MaskValueSet DEFAULT_FS_FEATURES = MaskValueSet.emptySet(FileSystemFlag.class); static { DEFAULT_FS_FEATURES.add(FileSystemFlag.CASE_PRESERVED_NAMES); @@ -61,7 +61,7 @@ public String getFileSystemName() { return this.fileSystemName; } - public EnumIntegerSet getFileSystemFeatures() { + public MaskValueSet getFileSystemFeatures() { return this.fileSystemFeatures; } @@ -104,7 +104,7 @@ public String toString() { return "VolumeInformation(maxComponentLength=" + this.getMaxComponentLength() + ", name=" + this.getName() + ", serialNumber=" + this.getSerialNumber() + ", fileSystemName=" + this.getFileSystemName() + ", fileSystemFeatures=" + this.getFileSystemFeatures() + ")"; } - public VolumeInformation(final int maxComponentLength, final String name, final int serialNumber, final String fileSystemName, final EnumIntegerSet fileSystemFeatures) { + public VolumeInformation(final int maxComponentLength, final String name, final int serialNumber, final String fileSystemName, final MaskValueSet fileSystemFeatures) { this.maxComponentLength = maxComponentLength; this.name = name; this.serialNumber = serialNumber; diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java index 39a765ae..674d17be 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ImmutableMountInfo.java @@ -4,8 +4,8 @@ import com.sun.jna.WString; import dev.dokan.dokan_java.DokanNativeMethods; import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.DokanOptions; -import dev.dokan.dokan_java.structure.EnumIntegerSet; public class ImmutableMountInfo implements ROMountInfo { @@ -64,8 +64,8 @@ public short getThreadCount() { } @Override - public EnumIntegerSet getMountOptions() { - return MountOption.fromInt(this.mountOptions); + public MaskValueSet getMountOptions() { + return MountOption.maskValueSet(this.mountOptions); } @Override @@ -75,7 +75,7 @@ public int getFlags() { @Override public boolean getFlag(MountOption flag) { - return (this.mountOptions & flag.getMask()) != 0; + return (this.mountOptions & flag.maskingValue()) != 0; } // @Override diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java index 77207214..134aad3f 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/MountInfo.java @@ -4,8 +4,8 @@ import com.sun.jna.WString; import dev.dokan.dokan_java.DokanNativeMethods; import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.DokanOptions; -import dev.dokan.dokan_java.structure.EnumIntegerSet; public class MountInfo implements RWMountInfo { @@ -69,13 +69,13 @@ public void setThreadCount(short threadCount) { } @Override - public EnumIntegerSet getMountOptions() { - return MountOption.fromInt(this.mountOptions); + public MaskValueSet getMountOptions() { + return MountOption.maskValueSet(this.mountOptions); } @Override - public void setMountOptions(EnumIntegerSet mountOptions) { - this.mountOptions = mountOptions.toInt(); + public void setMountOptions(MaskValueSet mountOptions) { + this.mountOptions = mountOptions.intValue(); } @Override @@ -90,7 +90,7 @@ public void setFlags(int flags) { @Override public boolean getFlag(MountOption flag) { - return (this.mountOptions & flag.getMask()) != 0; + return (this.mountOptions & flag.maskingValue()) != 0; } @Override @@ -106,7 +106,7 @@ public boolean unsetFlag(MountOption flag) { @Override public boolean updateFlag(MountOption flag, boolean value) { boolean prev = getFlag(flag); - this.mountOptions &= value ? flag.getMask() : ~flag.getMask(); + this.mountOptions &= value ? flag.maskingValue() : ~flag.maskingValue(); return prev; } diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java index 3323e266..9fb2b9a8 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/ROMountInfo.java @@ -2,8 +2,8 @@ import dev.dokan.dokan_java.constants.dokany.MountOption; +import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.DokanOptions; -import dev.dokan.dokan_java.structure.EnumIntegerSet; public interface ROMountInfo { @@ -12,7 +12,7 @@ public interface ROMountInfo { short getThreadCount(); - EnumIntegerSet getMountOptions(); + MaskValueSet getMountOptions(); int getFlags(); diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java index aee5093c..5d599e29 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/mountinfo/RWMountInfo.java @@ -2,14 +2,14 @@ import dev.dokan.dokan_java.constants.dokany.MountOption; -import dev.dokan.dokan_java.structure.EnumIntegerSet; +import dev.dokan.dokan_java.masking.MaskValueSet; public interface RWMountInfo extends ROMountInfo { void setThreadCount(short threadCount); - void setMountOptions(EnumIntegerSet mountOptions); + void setMountOptions(MaskValueSet mountOptions); void setFlags(int flags); From bffbce0bb32615f4ad28dbfe223ce88d6dc6bc16 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Wed, 3 Jun 2020 17:18:10 +0200 Subject: [PATCH 20/25] Improved support for generic/non-MS ReparsePointTags Added ReparsePointTag as base interface for all ReparsePointTags (extends EnumInteger) Changed MicrosoftReparsePointTag to implement ReparsePointTag Changed signature of generic/non-MS-specific methods in FindFileInfo to use ReparsePointTag-Interface See: https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags https://web.archive.org/web/20200603151710/https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags --- .../microsoft/MicrosoftReparsePointTag.java | 18 +++++++++++++++++- .../dokan_java/structure/ReparsePointTag.java | 13 +++++++++++++ .../dokan_java/wrappers/FindFileInfo.java | 7 ++++--- 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/main/java/dev/dokan/dokan_java/structure/ReparsePointTag.java diff --git a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java index 1a52b7d0..53f827e2 100644 --- a/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java +++ b/src/main/java/dev/dokan/dokan_java/constants/microsoft/MicrosoftReparsePointTag.java @@ -1,8 +1,11 @@ package dev.dokan.dokan_java.constants.microsoft; + import dev.dokan.dokan_java.masking.EnumInteger; +import dev.dokan.dokan_java.structure.ReparsePointTag; + -public enum MicrosoftReparsePointTag implements EnumInteger { +public enum MicrosoftReparsePointTag implements ReparsePointTag { IO_REPARSE_TAG_CSV(0x80000009), IO_REPARSE_TAG_DEDUP(0x80000013), @@ -16,6 +19,9 @@ public enum MicrosoftReparsePointTag implements EnumInteger { IO_REPARSE_TAG_SYMLINK(0xA000000C), IO_REPARSE_TAG_WIM(0x80000008); + private static final String SOURCE = "WinNT.h"; + private static final String DEFINED_BY = "Microsoft"; + private final int intValue; MicrosoftReparsePointTag(int intValue) { @@ -30,4 +36,14 @@ public static MicrosoftReparsePointTag fromInt(final int value) { public int intValue() { return this.intValue; } + + @Override + public String getSource() { + return SOURCE; + } + + @Override + public String getDefinedBy() { + return DEFINED_BY; + } } diff --git a/src/main/java/dev/dokan/dokan_java/structure/ReparsePointTag.java b/src/main/java/dev/dokan/dokan_java/structure/ReparsePointTag.java new file mode 100644 index 00000000..d3ea2cc5 --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/structure/ReparsePointTag.java @@ -0,0 +1,13 @@ +package dev.dokan.dokan_java.structure; + + +import dev.dokan.dokan_java.masking.EnumInteger; + + +public interface ReparsePointTag extends EnumInteger { + + String getSource(); + + String getDefinedBy(); + +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java index ca99ff1b..4a437a84 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/FindFileInfo.java @@ -6,6 +6,7 @@ import dev.dokan.dokan_java.constants.microsoft.MicrosoftReparsePointTag; import dev.dokan.dokan_java.masking.EnumInteger; import dev.dokan.dokan_java.masking.MaskValueSet; +import dev.dokan.dokan_java.structure.ReparsePointTag; import java.util.Objects; import java.util.function.Function; @@ -57,15 +58,15 @@ public & EnumInteger> T getReparsePointTag(T[] possibleValues return EnumInteger.enumFromInt(getReparsePointTagValue(), possibleValues); } - public void setReparsePointTag(T tag) { + public & ReparsePointTag> void setReparsePointTag(T tag) { setReparsePointTagValue(tag.intValue()); } - public > T getReparsePointTag(Function parser) { + public & ReparsePointTag> T getReparsePointTag(Function parser) { return parser.apply(getReparsePointTagValue()); } - public > void setReparsePointTag(T tag, Function parser) { + public & ReparsePointTag> void setReparsePointTag(T tag, Function parser) { setReparsePointTagValue(parser.apply(tag)); } From 8ba91fd0371f600fdfb00d27a02cce12f13b303e Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Mon, 8 Jun 2020 17:23:09 +0200 Subject: [PATCH 21/25] Updated DokanFileHandle to use ROMountInfo and added missing method Updated DokanFileHandle to use ROMountInfo instead of DokanOptions Added setFileInfo method This commit led to discovery of https://github.com/dokan-dev/dokan-java/issues/46 which leads to problems with this code. --- .../dokan_java/wrappers/DokanFileHandle.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java index 1e64a9f7..6350986d 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DokanFileHandle.java @@ -3,25 +3,34 @@ import dev.dokan.dokan_java.constants.dokany.DokanFileInfoFlag; import dev.dokan.dokan_java.masking.MaskValueSet; import dev.dokan.dokan_java.structure.DokanFileInfo; -import dev.dokan.dokan_java.structure.DokanOptions; +import dev.dokan.dokan_java.wrappers.mountinfo.MountInfo; +import dev.dokan.dokan_java.wrappers.mountinfo.ROMountInfo; import java.util.concurrent.atomic.AtomicInteger; -public class DokanFileHandle { //TODO Add Getters?! +public class DokanFileHandle { private static final long INVALID_HANDLE = 0L; private final AtomicInteger flags; private final long dokanContext; //DokanFileInfo tells us to "never modify". Happy to oblige + private final ROMountInfo mountInfo; + private long context; private int processId; - private DokanOptions dokanOpts; //TODO public DokanFileHandle(DokanFileInfo nativeInfo) { this.context = nativeInfo.Context; this.dokanContext = nativeInfo.DokanContext; this.processId = nativeInfo.ProcessId; - this.dokanOpts = nativeInfo.DokanOpts; //TODO Copy/Different link? + /* + * FIXME + * This copy is as expensive as it is useless. A reference to a stored MountInfo-Object would be far more useful. + * Due to bug/issue #46 this would be inherently unsafe, so it's a copy for now... + * + * See https://github.com/dokan-dev/dokan-java/issues/46 + */ + this.mountInfo = new MountInfo(nativeInfo.DokanOpts); MaskValueSet flagSet = MaskValueSet.emptySet(DokanFileInfoFlag.class); if(nativeInfo.deleteOnClose()) { @@ -49,6 +58,10 @@ public MaskValueSet getFileInfo() { return MaskValueSet.maskValueSet(this.flags.get(), DokanFileInfoFlag.values()); } + public void setFileInfo(MaskValueSet flagSet) { + this.flags.set(flagSet.intValue()); + } + public int getFlags() { return this.flags.get(); } @@ -102,11 +115,7 @@ public void setProcessId(int processId) { this.processId = processId; } - public DokanOptions getDokanOptions() { - return this.dokanOpts; - } - - public void setDokanOptions(DokanOptions dokanOpts) { - this.dokanOpts = dokanOpts; + public ROMountInfo getMountInfo() { + return mountInfo; } } \ No newline at end of file From 37eb2160fcc93e5cd717974afe6bc8f3d1004504 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Tue, 9 Jun 2020 19:12:53 +0200 Subject: [PATCH 22/25] Added check if only a single bit (flag) is set Added check if only a single bit (flag) is set to make sure that getFlag returns reliable results --- .../dev/dokan/dokan_java/wrappers/DesiredAccessMask.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java index fa0778e0..186b55e7 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -68,6 +68,13 @@ public boolean silentGetFlag(DirectoryAccessMask flag) { } public boolean getFlag(int flag) { + /* + * This may be more performant, but it doesn't really matter + * Integer.highestOneBit(flag) != Integer.lowestOneBit(flag) + */ + if(Integer.bitCount(flag) != 1) { + throw new IllegalArgumentException("Result for more than one flag is undefined!"); + } return (this.accessMask.get() & flag) != 0; } From 31330ab2060eccfae8a279c958b6d710df837dcd Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Tue, 9 Jun 2020 19:27:47 +0200 Subject: [PATCH 23/25] Added check if only a single bit (flag) is set to updateFlag Added check if only a single bit (flag) is set to make sure that updateFlag operates reliably Externalized check --- .../wrappers/DesiredAccessMask.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java index 186b55e7..342403a6 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -68,13 +68,8 @@ public boolean silentGetFlag(DirectoryAccessMask flag) { } public boolean getFlag(int flag) { - /* - * This may be more performant, but it doesn't really matter - * Integer.highestOneBit(flag) != Integer.lowestOneBit(flag) - */ - if(Integer.bitCount(flag) != 1) { - throw new IllegalArgumentException("Result for more than one flag is undefined!"); - } + ensureSingleFlag(flag); + return (this.accessMask.get() & flag) != 0; } @@ -136,10 +131,26 @@ public boolean silentUpdateFlag(DirectoryAccessMask flag, boolean value) { } public boolean updateFlag(int flag, boolean value) { + ensureSingleFlag(flag); + int prev = this.accessMask.getAndUpdate(current -> current & (value ? flag : ~flag)); return (prev & flag) != 0; } + private void ensureSingleFlag(int flag) { + if(!isSingleFlag(flag)) { + throw new IllegalArgumentException("Result for more than one flag is undefined!"); + } + } + + private boolean isSingleFlag(int flag) { + /* + * This may be more performant, but it doesn't really matter + * Integer.highestOneBit(flag) != Integer.lowestOneBit(flag) + */ + return Integer.bitCount(flag) == 1; + } + private FileAccessMask getFileAccessMask(DirectoryAccessMask attribute) { //This lookup is fine, but a different kind of mapping would be preferable switch(attribute) { From 72296c4ad21eabbd6756d27ad7833a52ba9c6cf4 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 18 Jun 2020 23:04:48 +0200 Subject: [PATCH 24/25] Adopted changes of AccessMaskFlags to DesiredAccessMask --- .../wrappers/DesiredAccessMask.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java index 342403a6..6575d03f 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -1,9 +1,9 @@ package dev.dokan.dokan_java.wrappers; -import dev.dokan.dokan_java.constants.microsoft.AccessMask; -import dev.dokan.dokan_java.constants.microsoft.DirectoryAccessMask; -import dev.dokan.dokan_java.constants.microsoft.FileAccessMask; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; +import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.BasicAccessMaskFlag; +import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.DirectoryAccessMaskFlag; +import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.FileAccessMaskFlag; import dev.dokan.dokan_java.masking.MaskValueSet; import java.util.concurrent.atomic.AtomicInteger; @@ -28,12 +28,12 @@ public DesiredAccessMask(int rawAccessMask, boolean isDirectory) { this.accessMask = new AtomicInteger(rawAccessMask); } - public MaskValueSet getBasicRights() { - return MaskValueSet.maskValueSet(this.accessMask.get(), AccessMask.values()); + public MaskValueSet getBasicRights() { + return MaskValueSet.maskValueSet(this.accessMask.get(), BasicAccessMaskFlag.values()); } - public MaskValueSet getSpecificRights() { - return MaskValueSet.maskValueSet(this.accessMask.get(), FileAccessMask.values()); + public MaskValueSet getSpecificRights() { + return MaskValueSet.maskValueSet(this.accessMask.get(), FileAccessMaskFlag.values()); } public boolean isDirectory() { @@ -48,22 +48,22 @@ public void setAccessMask(int accessMask) { this.accessMask.set(accessMask); } - public boolean getFlag(AccessMask flag) { + public boolean getFlag(BasicAccessMaskFlag flag) { return getFlag(flag.maskingValue()); } - public boolean getFlag(FileAccessMask flag) { + public boolean getFlag(FileAccessMaskFlag flag) { return getFlag(flag.maskingValue()); } - public boolean getFlag(DirectoryAccessMask flag) { + public boolean getFlag(DirectoryAccessMaskFlag flag) { if(!this.isDirectory) { throw new IllegalArgumentException("Not a directory!"); } return silentGetFlag(flag); } - public boolean silentGetFlag(DirectoryAccessMask flag) { + public boolean silentGetFlag(DirectoryAccessMaskFlag flag) { return getFlag(flag.maskingValue()); } @@ -73,60 +73,60 @@ public boolean getFlag(int flag) { return (this.accessMask.get() & flag) != 0; } - public boolean setFlag(AccessMask flag) { + public boolean setFlag(BasicAccessMaskFlag flag) { return updateFlag(flag, true); } - public boolean unsetFlag(AccessMask flag) { + public boolean unsetFlag(BasicAccessMaskFlag flag) { return updateFlag(flag, false); } - public boolean updateFlag(AccessMask flag, boolean value) { + public boolean updateFlag(BasicAccessMaskFlag flag, boolean value) { return updateFlag(flag.maskingValue(), value); } - public boolean setFlag(FileAccessMask flag) { + public boolean setFlag(FileAccessMaskFlag flag) { return updateFlag(flag, true); } - public boolean unsetFlag(FileAccessMask flag) { + public boolean unsetFlag(FileAccessMaskFlag flag) { return updateFlag(flag, false); } - public boolean updateFlag(FileAccessMask flag, boolean value) { + public boolean updateFlag(FileAccessMaskFlag flag, boolean value) { return updateFlag(flag.maskingValue(), value); } - public boolean setFlag(DirectoryAccessMask flag) { + public boolean setFlag(DirectoryAccessMaskFlag flag) { if(!this.isDirectory) { throw new IllegalArgumentException("Not a directory!"); } return silentSetFlag(flag); } - public boolean unsetFlag(DirectoryAccessMask flag) { + public boolean unsetFlag(DirectoryAccessMaskFlag flag) { if(!this.isDirectory) { throw new IllegalArgumentException("Not a directory!"); } return silentUnsetFlag(flag); } - public boolean updateFlag(DirectoryAccessMask flag, boolean value) { + public boolean updateFlag(DirectoryAccessMaskFlag flag, boolean value) { if(!this.isDirectory) { throw new IllegalArgumentException("Not a directory!"); } return silentUpdateFlag(flag, value); } - public boolean silentSetFlag(DirectoryAccessMask flag) { + public boolean silentSetFlag(DirectoryAccessMaskFlag flag) { return silentUpdateFlag(flag, true); } - public boolean silentUnsetFlag(DirectoryAccessMask flag) { + public boolean silentUnsetFlag(DirectoryAccessMaskFlag flag) { return silentUpdateFlag(flag, false); } - public boolean silentUpdateFlag(DirectoryAccessMask flag, boolean value) { + public boolean silentUpdateFlag(DirectoryAccessMaskFlag flag, boolean value) { return updateFlag(flag.maskingValue(), value); } @@ -151,13 +151,13 @@ private boolean isSingleFlag(int flag) { return Integer.bitCount(flag) == 1; } - private FileAccessMask getFileAccessMask(DirectoryAccessMask attribute) { + private FileAccessMaskFlag getFileAccessMaskFlag(DirectoryAccessMaskFlag attribute) { //This lookup is fine, but a different kind of mapping would be preferable switch(attribute) { case LIST_DIRECTORY: //1 - return FileAccessMask.READ_DATA; + return FileAccessMaskFlag.READ_DATA; case TRAVERSE: //32 - return FileAccessMask.EXECUTE; + return FileAccessMaskFlag.EXECUTE; } throw new IllegalStateException(); } From 05c1c398a911ec07f228bb6fed2f46c52e4fda31 Mon Sep 17 00:00:00 2001 From: JaniruTEC Date: Thu, 18 Jun 2020 23:42:12 +0200 Subject: [PATCH 25/25] Moved support for Basic Rights to a new base class Created BasicDesiredAccessMask as base class for DesiredAccessMask Moved all methods concerning basic rights to the new base class Renamed getFileAccessMask to getFileAccessMaskFlag to reflect the changes to the AccessMaskFlags --- .../wrappers/BasicDesiredAccessMask.java | 86 +++++++++++++++++++ .../wrappers/DesiredAccessMask.java | 66 +------------- 2 files changed, 90 insertions(+), 62 deletions(-) create mode 100644 src/main/java/dev/dokan/dokan_java/wrappers/BasicDesiredAccessMask.java diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/BasicDesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/BasicDesiredAccessMask.java new file mode 100644 index 00000000..7e06446e --- /dev/null +++ b/src/main/java/dev/dokan/dokan_java/wrappers/BasicDesiredAccessMask.java @@ -0,0 +1,86 @@ +package dev.dokan.dokan_java.wrappers; + + +import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.BasicAccessMaskFlag; +import dev.dokan.dokan_java.masking.MaskValueSet; + +import java.util.concurrent.atomic.AtomicInteger; + + +public class BasicDesiredAccessMask { + + private final static int ACCESS_MASK_VALUES = MaskValueSet.of(BasicAccessMaskFlag.values()).intValue(); + + protected final AtomicInteger accessMask; + + public BasicDesiredAccessMask(MaskValueSet accessMask) { + this(accessMask.intValue()); + } + + public BasicDesiredAccessMask(int accessMask) { + this.accessMask = new AtomicInteger(accessMask); + } + + public MaskValueSet getBasicRights() { + return BasicAccessMaskFlag.maskValueSet(this.accessMask.get()); + } + + public int getBasicAccessMask() { + return getAccessMask() & ACCESS_MASK_VALUES; + } + + public void setBasicAccessMask(int accessMask) { + setAccessMask(accessMask & ACCESS_MASK_VALUES); + } + + public int getAccessMask() { + return this.accessMask.get(); + } + + public void setAccessMask(int accessMask) { + this.accessMask.set(accessMask); + } + + public boolean getFlag(BasicAccessMaskFlag flag) { + return getFlag(flag.maskingValue()); + } + + public boolean getFlag(int flag) { + ensureSingleFlag(flag); + + return (this.accessMask.get() & flag) != 0; + } + + public boolean setFlag(BasicAccessMaskFlag flag) { + return updateFlag(flag, true); + } + + public boolean unsetFlag(BasicAccessMaskFlag flag) { + return updateFlag(flag, false); + } + + public boolean updateFlag(BasicAccessMaskFlag flag, boolean value) { + return updateFlag(flag.maskingValue(), value); + } + + public boolean updateFlag(int flag, boolean value) { + ensureSingleFlag(flag); + + int prev = this.accessMask.getAndUpdate(current -> current & (value ? flag : ~flag)); + return (prev & flag) != 0; + } + + protected void ensureSingleFlag(int flag) { + if (!isSingleFlag(flag)) { + throw new IllegalArgumentException("Result for more than one flag is undefined!"); + } + } + + protected boolean isSingleFlag(int flag) { + /* + * This may be more performant, but it doesn't really matter + * Integer.highestOneBit(flag) != Integer.lowestOneBit(flag) + */ + return Integer.bitCount(flag) == 1; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java index 6575d03f..c279b5fa 100644 --- a/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java +++ b/src/main/java/dev/dokan/dokan_java/wrappers/DesiredAccessMask.java @@ -1,17 +1,14 @@ package dev.dokan.dokan_java.wrappers; import dev.dokan.dokan_java.constants.microsoft.FileAttribute; -import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.BasicAccessMaskFlag; import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.DirectoryAccessMaskFlag; import dev.dokan.dokan_java.constants.microsoft.accessmaskflags.FileAccessMaskFlag; import dev.dokan.dokan_java.masking.MaskValueSet; -import java.util.concurrent.atomic.AtomicInteger; -public class DesiredAccessMask { +public class DesiredAccessMask extends BasicDesiredAccessMask { private final boolean isDirectory; - private final AtomicInteger accessMask; public DesiredAccessMask(int rawAccessMask, int rawFileAttributes) { this(rawAccessMask, (rawFileAttributes & FileAttribute.DIRECTORY.maskingValue()) != 0); @@ -24,34 +21,18 @@ public DesiredAccessMask(int rawAccessMask, MaskValueSet fileAttr //TODO Check for illegal flags if isDirectory=true //See https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatefile Note below first table public DesiredAccessMask(int rawAccessMask, boolean isDirectory) { + super(rawAccessMask); this.isDirectory = isDirectory; - this.accessMask = new AtomicInteger(rawAccessMask); - } - - public MaskValueSet getBasicRights() { - return MaskValueSet.maskValueSet(this.accessMask.get(), BasicAccessMaskFlag.values()); } public MaskValueSet getSpecificRights() { - return MaskValueSet.maskValueSet(this.accessMask.get(), FileAccessMaskFlag.values()); + return FileAccessMaskFlag.maskValueSet(this.accessMask.get()); } public boolean isDirectory() { return this.isDirectory; } - public int getAccessMask() { - return this.accessMask.get(); - } - - public void setAccessMask(int accessMask) { - this.accessMask.set(accessMask); - } - - public boolean getFlag(BasicAccessMaskFlag flag) { - return getFlag(flag.maskingValue()); - } - public boolean getFlag(FileAccessMaskFlag flag) { return getFlag(flag.maskingValue()); } @@ -67,24 +48,6 @@ public boolean silentGetFlag(DirectoryAccessMaskFlag flag) { return getFlag(flag.maskingValue()); } - public boolean getFlag(int flag) { - ensureSingleFlag(flag); - - return (this.accessMask.get() & flag) != 0; - } - - public boolean setFlag(BasicAccessMaskFlag flag) { - return updateFlag(flag, true); - } - - public boolean unsetFlag(BasicAccessMaskFlag flag) { - return updateFlag(flag, false); - } - - public boolean updateFlag(BasicAccessMaskFlag flag, boolean value) { - return updateFlag(flag.maskingValue(), value); - } - public boolean setFlag(FileAccessMaskFlag flag) { return updateFlag(flag, true); } @@ -130,28 +93,7 @@ public boolean silentUpdateFlag(DirectoryAccessMaskFlag flag, boolean value) { return updateFlag(flag.maskingValue(), value); } - public boolean updateFlag(int flag, boolean value) { - ensureSingleFlag(flag); - - int prev = this.accessMask.getAndUpdate(current -> current & (value ? flag : ~flag)); - return (prev & flag) != 0; - } - - private void ensureSingleFlag(int flag) { - if(!isSingleFlag(flag)) { - throw new IllegalArgumentException("Result for more than one flag is undefined!"); - } - } - - private boolean isSingleFlag(int flag) { - /* - * This may be more performant, but it doesn't really matter - * Integer.highestOneBit(flag) != Integer.lowestOneBit(flag) - */ - return Integer.bitCount(flag) == 1; - } - - private FileAccessMaskFlag getFileAccessMaskFlag(DirectoryAccessMaskFlag attribute) { + private FileAccessMaskFlag getFileAccessMask(DirectoryAccessMaskFlag attribute) { //This lookup is fine, but a different kind of mapping would be preferable switch(attribute) { case LIST_DIRECTORY: //1