mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
4b65871747 | |||
eaa0d7d7d2 | |||
facbc2c1b5 | |||
e5879a9cb0 | |||
0a91292e05 | |||
1a879e3302 | |||
98421fe11b | |||
f6fef97a10 | |||
f0931a0cf2 | |||
9ecb6541cf | |||
d816d607f4 | |||
f3df3f6dd2 | |||
7527155cb8 | |||
868812d248 | |||
20680fa5b5 | |||
00d4aba946 | |||
fadcd84ca9 | |||
966e08e7c1 | |||
8d83d46e7f | |||
cdcd6af81d | |||
9567b94d37 | |||
50a28c4284 | |||
87a1d5468d | |||
fda950b90e | |||
4ccf0d2085 | |||
2c42dc535c | |||
84ab502b98 | |||
0c90a69b27 | |||
2ed46a39fa | |||
cf13cac438 |
2
.github/ISSUE_TEMPLATE/question.md
vendored
2
.github/ISSUE_TEMPLATE/question.md
vendored
@ -5,4 +5,4 @@ about: Questions are better asked in the WinFsp Google Group. However you may as
|
|||||||
|
|
||||||
## Question
|
## Question
|
||||||
|
|
||||||
_Please consider asking questions in the [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp) instead. Before asking a question please also consult the [WinFsp Frequently Asked Questions](https://github.com/billziss-gh/winfsp/wiki/Frequently-Asked-Questions)._
|
_Please consider asking questions in the [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp) instead. Before asking a question please also consult the [WinFsp Frequently Asked Questions](https://github.com/winfsp/winfsp/wiki/Frequently-Asked-Questions)._
|
||||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Before submitting this PR please review this checklist. Ideally all checkmarks should be checked upon submitting. (Use an x inside square brackets like so: [x])
|
Before submitting this PR please review this checklist. Ideally all checkmarks should be checked upon submitting. (Use an x inside square brackets like so: [x])
|
||||||
|
|
||||||
- [ ] **Contributing**: You MUST read and be willing to accept the [CONTRIBUTOR AGREEMENT](https://github.com/billziss-gh/winfsp/blob/master/Contributors.asciidoc). The agreement gives joint copyright interests in your contributions to you and the original WinFsp author. If you have already accepted the [CONTRIBUTOR AGREEMENT](https://github.com/billziss-gh/winfsp/blob/master/Contributors.asciidoc) you do not need to do so again.
|
- [ ] **Contributing**: You MUST read and be willing to accept the [CONTRIBUTOR AGREEMENT](https://github.com/winfsp/winfsp/blob/master/Contributors.asciidoc). The agreement gives joint copyright interests in your contributions to you and the original WinFsp author. If you have already accepted the [CONTRIBUTOR AGREEMENT](https://github.com/winfsp/winfsp/blob/master/Contributors.asciidoc) you do not need to do so again.
|
||||||
- [ ] **Topic branch**: Avoid creating the PR off the master branch of your fork. Consider creating a topic branch and request a pull from that. This allows you to add commits to the master branch of your fork without affecting this PR.
|
- [ ] **Topic branch**: Avoid creating the PR off the master branch of your fork. Consider creating a topic branch and request a pull from that. This allows you to add commits to the master branch of your fork without affecting this PR.
|
||||||
- [ ] **No tabs**: Consistently use SPACES everywhere. NO TABS, unless the file format requires it (e.g. Makefile).
|
- [ ] **No tabs**: Consistently use SPACES everywhere. NO TABS, unless the file format requires it (e.g. Makefile).
|
||||||
- [ ] **Style**: Follow the same code style as the rest of the project.
|
- [ ] **Style**: Follow the same code style as the rest of the project.
|
||||||
|
10
.github/workflows/avm.yml
vendored
10
.github/workflows/avm.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
|||||||
- uses: billziss-gh/avm@v1
|
- uses: billziss-gh/avm@v1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.7/winfsp-1.7.20172.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.7/winfsp-1.7.20172.msi
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.8/winfsp-1.8.20304.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.8/winfsp-1.8.20304.msi
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.9/winfsp-1.9.21096.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.9/winfsp-1.9.21096.msi
|
||||||
https://github.com/billziss-gh/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
||||||
|
34
Changelog.md
34
Changelog.md
@ -1,9 +1,41 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
|
||||||
|
## v1.11B2 (2022+ARM64 Beta2)
|
||||||
|
|
||||||
|
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||||
|
|
||||||
|
- [NEW] A new file system operation has been added to the FUSE API:
|
||||||
|
|
||||||
|
```C
|
||||||
|
int (*getpath)(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi);
|
||||||
|
```
|
||||||
|
|
||||||
|
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
|
||||||
|
|
||||||
|
- [NEW] Many performance improvements:
|
||||||
|
|
||||||
|
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
|
||||||
|
|
||||||
|
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
|
||||||
|
|
||||||
|
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to a user mode file system.
|
||||||
|
|
||||||
|
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
|
||||||
|
|
||||||
|
- [NEW] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
|
||||||
|
|
||||||
|
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
||||||
|
|
||||||
|
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
|
||||||
|
|
||||||
|
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
|
||||||
|
|
||||||
|
|
||||||
## v1.11B1 (2022+ARM64 Beta1)
|
## v1.11B1 (2022+ARM64 Beta1)
|
||||||
|
|
||||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/billziss-gh/winfsp/wiki/WinFsp-on-ARM64).
|
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||||
|
|
||||||
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
||||||
|
|
||||||
|
14
README.md
14
README.md
@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<b>Download</b><br>
|
<b>Download</b><br>
|
||||||
<a href="https://github.com/billziss-gh/winfsp/releases/latest">
|
<a href="https://github.com/winfsp/winfsp/releases/latest">
|
||||||
<img src="https://img.shields.io/github/release/billziss-gh/winfsp.svg?label=stable&style=for-the-badge"/>
|
<img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/billziss-gh/winfsp/releases">
|
<a href="https://github.com/winfsp/winfsp/releases">
|
||||||
<img src="https://img.shields.io/github/release/billziss-gh/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge"/>
|
<img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://chocolatey.org/packages/winfsp">
|
<a href="https://chocolatey.org/packages/winfsp">
|
||||||
<img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/>
|
<img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/>
|
||||||
@ -53,7 +53,7 @@ WinFsp strives for compatibility with NTFS and file system correctness. For the
|
|||||||
WinFsp has an easy to use but comprehensive API.
|
WinFsp has an easy to use but comprehensive API.
|
||||||
|
|
||||||
* This simple [Tutorial](doc/WinFsp-Tutorial.asciidoc) explains how to build a file system.
|
* This simple [Tutorial](doc/WinFsp-Tutorial.asciidoc) explains how to build a file system.
|
||||||
* Consult the [API Reference](http://www.secfs.net/winfsp/apiref/) for native development.
|
* Consult the [API Reference](https://winfsp.dev/apiref) for native development.
|
||||||
* Includes .NET layer for managed development. See [src/dotnet](src/dotnet).
|
* Includes .NET layer for managed development. See [src/dotnet](src/dotnet).
|
||||||
* Includes FUSE 2.8 compatibility layer: [fuse/fuse.h](inc/fuse/fuse.h)
|
* Includes FUSE 2.8 compatibility layer: [fuse/fuse.h](inc/fuse/fuse.h)
|
||||||
* Includes FUSE 3.2 compatibility layer: [fuse3/fuse.h](inc/fuse3/fuse.h)
|
* Includes FUSE 3.2 compatibility layer: [fuse3/fuse.h](inc/fuse3/fuse.h)
|
||||||
@ -63,7 +63,7 @@ WinFsp has an easy to use but comprehensive API.
|
|||||||
* Signed drivers provided on every release.
|
* Signed drivers provided on every release.
|
||||||
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
|
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
|
||||||
|
|
||||||
To learn more about WinFsp, please visit its website: http://www.secfs.net/winfsp/
|
To learn more about WinFsp, please visit its website: https://winfsp.dev
|
||||||
|
|
||||||
## Project Organization
|
## Project Organization
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ I am looking for help in the following areas:
|
|||||||
|
|
||||||
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
||||||
* If you are working with a language other than C/C++ (e.g. Delphi, Java, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
* If you are working with a language other than C/C++ (e.g. Delphi, Java, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
||||||
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
|
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/winfsp/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
|
||||||
|
|
||||||
In all cases I can provide ideas and/or support.
|
In all cases I can provide ideas and/or support.
|
||||||
|
|
||||||
|
10
appveyor.yml
10
appveyor.yml
@ -13,9 +13,9 @@ environment:
|
|||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
#- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
# CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
# TESTING: Func
|
TESTING: Func
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
TESTING: Func
|
TESTING: Func
|
||||||
@ -68,7 +68,9 @@ build_script:
|
|||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- choco install winfsp -s build\VStudio\build\%CONFIGURATION% -y --pre
|
- choco install winfsp -s build\VStudio\build\%CONFIGURATION% -y --pre
|
||||||
- if %TESTING%==Func appveyor DownloadFile http://www.secfs.net/Test.Filter.Driver.zip && 7z x Test.Filter.Driver.zip
|
- if %TESTING%==Func appveyor DownloadFile https://winfsp.dev/assets/pvt/Test.Filter.Driver.zip.001
|
||||||
|
- if %TESTING%==Func appveyor DownloadFile https://winfsp.dev/assets/pvt/Test.Filter.Driver.zip.002
|
||||||
|
- if %TESTING%==Func 7z x Test.Filter.Driver.zip.001
|
||||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
<!-- git revision -->
|
<!-- git revision -->
|
||||||
<MyGitRoot>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), .git/HEAD))</MyGitRoot>
|
<MyGitRoot>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), .git/HEAD))</MyGitRoot>
|
||||||
<MyGitHead>$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/HEAD).Trim())</MyGitHead>
|
<MyGitHead Condition=" Exists('$(MyGitRoot)/.git/HEAD')">$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/HEAD).Trim())</MyGitHead>
|
||||||
|
<MyGitHead Condition="!Exists('$(MyGitRoot)/.git/HEAD')">0000000</MyGitHead>
|
||||||
<MyGitRevision Condition="$(MyGitHead.StartsWith(ref: )) And Exists('$(MyGitRoot)/.git/$(MyGitHead.Substring(5))')">$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/$(MyGitHead.Substring(5))).Trim().Substring(0, 7))</MyGitRevision>
|
<MyGitRevision Condition="$(MyGitHead.StartsWith(ref: )) And Exists('$(MyGitRoot)/.git/$(MyGitHead.Substring(5))')">$([System.IO.File]::ReadAllText($(MyGitRoot)/.git/$(MyGitHead.Substring(5))).Trim().Substring(0, 7))</MyGitRevision>
|
||||||
<MyGitRevision Condition="$(MyGitHead.StartsWith(ref: )) And !Exists('$(MyGitRoot)/.git/$(MyGitHead.Substring(5))')">$([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(MyGitRoot)/.git/packed-refs)), '[0-9a-fA-F]{40,}.*$(MyGitHead.Substring(5))').Value.Substring(0, 7))</MyGitRevision>
|
<MyGitRevision Condition="$(MyGitHead.StartsWith(ref: )) And !Exists('$(MyGitRoot)/.git/$(MyGitHead.Substring(5))')">$([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText($(MyGitRoot)/.git/packed-refs)), '[0-9a-fA-F]{40,}.*$(MyGitHead.Substring(5))').Value.Substring(0, 7))</MyGitRevision>
|
||||||
<MyGitRevision Condition="!$(MyGitHead.StartsWith(ref: ))">$(MyGitHead.Substring(0, 7))</MyGitRevision>
|
<MyGitRevision Condition="!$(MyGitHead.StartsWith(ref: ))">$(MyGitHead.Substring(0, 7))</MyGitRevision>
|
||||||
@ -19,9 +20,12 @@
|
|||||||
|
|
||||||
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2022+ARM64 Beta1</MyProductVersion>
|
<MyProductVersion>2022+ARM64 Beta2</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>Beta</MyProductStage>
|
||||||
|
|
||||||
|
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
|
||||||
|
<MyCertIssuer>DigiCert</MyCertIssuer>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
|
<MyFullVersion>$(MyCanonicalVersion).$(MyBuildNumber).$(MyGitRevision)</MyFullVersion>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
From: https://github.com/billziss-gh/winfsp/blob/master/License.txt
|
From: https://github.com/winfsp/winfsp/blob/master/License.txt
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ VERIFICATION
|
|||||||
Verification is intended to assist the Chocolatey moderators and community
|
Verification is intended to assist the Chocolatey moderators and community
|
||||||
in verifying that this package's contents are trustworthy.
|
in verifying that this package's contents are trustworthy.
|
||||||
|
|
||||||
WinFsp GitHub repository: https://github.com/billziss-gh/winfsp
|
WinFsp GitHub repository: https://github.com/winfsp/winfsp
|
||||||
WinFsp MSI releases : https://github.com/billziss-gh/winfsp/releases
|
WinFsp MSI releases : https://github.com/winfsp/winfsp/releases
|
||||||
|
|
||||||
You may use the Windows certutil utility to confirm the hash of the MSI
|
You may use the Windows certutil utility to confirm the hash of the MSI
|
||||||
included in this package against the WinFsp MSI release of the same version.
|
included in this package against the WinFsp MSI release of the same version.
|
||||||
@ -12,4 +12,3 @@ For example, for WinFsp version 1.0.17072 the command line to use is:
|
|||||||
certutil -hashfile winfsp-1.0.17072.msi SHA256
|
certutil -hashfile winfsp-1.0.17072.msi SHA256
|
||||||
|
|
||||||
The certutil output of the MSI in this package is included below.
|
The certutil output of the MSI in this package is included below.
|
||||||
|
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>winfsp</id>
|
<id>winfsp</id>
|
||||||
<version>$version$</version>
|
<version>$version$</version>
|
||||||
<packageSourceUrl>https://github.com/billziss-gh/winfsp/tree/master/build/choco</packageSourceUrl>
|
<packageSourceUrl>https://github.com/winfsp/winfsp/tree/master/build/choco</packageSourceUrl>
|
||||||
<owners>Bill Zissimopoulos</owners>
|
<owners>Bill Zissimopoulos</owners>
|
||||||
|
|
||||||
<title>WinFsp</title>
|
<title>WinFsp</title>
|
||||||
<authors>Bill Zissimopoulos</authors>
|
<authors>Bill Zissimopoulos</authors>
|
||||||
<projectUrl>https://github.com/billziss-gh/winfsp</projectUrl>
|
<projectUrl>https://github.com/winfsp/winfsp</projectUrl>
|
||||||
<iconUrl>https://github.com/billziss-gh/winfsp/raw/master/art/winfsp-solid.png</iconUrl>
|
<iconUrl>https://github.com/winfsp/winfsp/raw/master/art/winfsp-solid.png</iconUrl>
|
||||||
<copyright>Bill Zissimopoulos</copyright>
|
<copyright>Bill Zissimopoulos</copyright>
|
||||||
<licenseUrl>https://github.com/billziss-gh/winfsp/blob/master/License.txt</licenseUrl>
|
<licenseUrl>https://github.com/winfsp/winfsp/blob/master/License.txt</licenseUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<projectSourceUrl>https://github.com/billziss-gh/winfsp</projectSourceUrl>
|
<projectSourceUrl>https://github.com/winfsp/winfsp</projectSourceUrl>
|
||||||
<docsUrl>https://github.com/billziss-gh/winfsp/tree/master/doc</docsUrl>
|
<docsUrl>https://github.com/winfsp/winfsp/tree/master/doc</docsUrl>
|
||||||
<mailingListUrl>https://groups.google.com/forum/#!forum/winfsp</mailingListUrl>
|
<mailingListUrl>https://groups.google.com/forum/#!forum/winfsp</mailingListUrl>
|
||||||
<bugTrackerUrl>https://github.com/billziss-gh/winfsp/issues</bugTrackerUrl>
|
<bugTrackerUrl>https://github.com/winfsp/winfsp/issues</bugTrackerUrl>
|
||||||
<tags>driver filesystem fuse gplv3 windows-kernel admin</tags>
|
<tags>driver filesystem fuse gplv3 windows-kernel admin</tags>
|
||||||
<summary>Windows File System Proxy - FUSE for Windows</summary>
|
<summary>Windows File System Proxy - FUSE for Windows</summary>
|
||||||
<description>
|
<description>
|
||||||
@ -39,7 +39,7 @@ To verify installation:
|
|||||||
* For Cygwin: `net use m: '\\memfs64\share'`
|
* For Cygwin: `net use m: '\\memfs64\share'`
|
||||||
* To delete the drive: `net use m: /delete`
|
* To delete the drive: `net use m: /delete`
|
||||||
</description>
|
</description>
|
||||||
<releaseNotes>https://github.com/billziss-gh/winfsp/blob/master/Changelog.asciidoc</releaseNotes>
|
<releaseNotes>https://github.com/winfsp/winfsp/blob/master/Changelog.md</releaseNotes>
|
||||||
|
|
||||||
<!--<dependencies>
|
<!--<dependencies>
|
||||||
<dependency id="chocolatey-uninstall.extension" />
|
<dependency id="chocolatey-uninstall.extension" />
|
||||||
|
@ -5,28 +5,31 @@ This document contains a list of known open-source file systems and file system
|
|||||||
== File Systems
|
== File Systems
|
||||||
|
|
||||||
- https://github.com/wesley1975/blobfs-win[blobfs-win] - The native porting of the blobfs on the windows platform, blobfs can help you mount the Azure Blob storage as the local disk driver, no matter it is a Linux system or a Windows system.
|
- https://github.com/wesley1975/blobfs-win[blobfs-win] - The native porting of the blobfs on the windows platform, blobfs can help you mount the Azure Blob storage as the local disk driver, no matter it is a Linux system or a Windows system.
|
||||||
|
- https://github.com/cryptomator/cryptomator[Cryptomator] - Multi-platform transparent client-side encryption of your files in the cloud
|
||||||
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
- https://github.com/vgough/encfs[EncFS] - an Encrypted Filesystem for FUSE
|
||||||
- https://github.com/lowleveldesign/fsmemfs[fsmemfs] - Memory File System written in F#
|
- https://github.com/lowleveldesign/fsmemfs[fsmemfs] - Memory File System written in F#
|
||||||
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
|
||||||
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
|
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
|
||||||
- https://github.com/billziss-gh/hubfs[hubfs] - File system for GitHub
|
- https://github.com/winfsp/hubfs[hubfs] - File system for GitHub
|
||||||
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
|
||||||
- https://github.com/billziss-gh/nfs-win[nfs-win] - NFS for Windows
|
- https://github.com/winfsp/nfs-win[nfs-win] - NFS for Windows
|
||||||
- https://github.com/billziss-gh/objfs[objfs] - Object Storage File System
|
- https://github.com/winfsp/objfs[objfs] - Object Storage File System
|
||||||
- https://github.com/ncw/rclone[rclone] - rsync for cloud storage
|
- https://github.com/ncw/rclone[rclone] - rsync for cloud storage
|
||||||
- https://github.com/hasse69/rar2fs[rar2fs] - FUSE file system for reading RAR archives
|
- https://github.com/hasse69/rar2fs[rar2fs] - FUSE file system for reading RAR archives
|
||||||
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
- https://github.com/billziss-gh/redditfs[redditfs] - ls -l /r/programming
|
||||||
|
- https://github.com/s3fs-fuse/s3fs-fuse[s3fs-fuse] - FUSE-based file system backed by Amazon S3
|
||||||
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
- https://github.com/netheril96/securefs[securefs] - Filesystem in userspace (FUSE) with transparent authenticated encryption
|
||||||
- https://github.com/billziss-gh/sshfs-win[sshfs-win] - SSHFS for Windows
|
- https://github.com/winfsp/sshfs-win[sshfs-win] - SSHFS for Windows
|
||||||
- https://github.com/printpagestopdf/WordpressDrive[WordpressDrive] - Windows Userspace Filesystem based on WinFsp that presents a Wordpress Site as a Windows Drive
|
- https://github.com/printpagestopdf/WordpressDrive[WordpressDrive] - Windows Userspace Filesystem based on WinFsp that presents a Wordpress Site as a Windows Drive
|
||||||
- https://github.com/emoose/xbox-winfsp[xbox-winfsp] - Adds native support to Windows for the FATX, STFS & GDFX (aka XGD/XDVDFS) Xbox filesystems.
|
- https://github.com/emoose/xbox-winfsp[xbox-winfsp] - Adds native support to Windows for the FATX, STFS & GDFX (aka XGD/XDVDFS) Xbox filesystems.
|
||||||
- https://github.com/UtrechtUniversity/YodaDrive[YodaDrive] - Mount a Yoda drive as a local drive
|
- https://github.com/UtrechtUniversity/YodaDrive[YodaDrive] - Mount a Yoda drive as a local drive
|
||||||
|
|
||||||
== File System Libraries
|
== File System Libraries
|
||||||
|
|
||||||
- https://github.com/billziss-gh/cgofuse[Go: cgofuse] - Cross-platform FUSE library for Go
|
- https://github.com/winfsp/cgofuse[Go: cgofuse] - Cross-platform FUSE library for Go
|
||||||
- https://github.com/DuroSoft/fuse-bindings[Nodejs: fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
|
||||||
- https://github.com/SerCeMan/jnr-fuse[Java: jnr-fuse] - FUSE implementation in Java using Java Native Runtime (JNR)
|
- https://github.com/SerCeMan/jnr-fuse[Java: jnr-fuse] - FUSE implementation in Java using Java Native Runtime (JNR)
|
||||||
|
- https://github.com/jnr-winfsp-team/jnr-winfsp[Java: jnr-winfsp] - A Java binding for WinFsp using Java Native Runtime (JNR)
|
||||||
|
- https://github.com/DuroSoft/fuse-bindings[Nodejs: fuse-bindings] - Fully maintained FUSE bindings for Node that aims to cover the entire FUSE api
|
||||||
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
||||||
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||||
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
||||||
|
@ -6,7 +6,7 @@ This document compares the "native" WinFsp API to the FUSE API and provides a ra
|
|||||||
|
|
||||||
WinFsp provides two different but conceptually similar API's for the same purpose of implementing a user mode file system:
|
WinFsp provides two different but conceptually similar API's for the same purpose of implementing a user mode file system:
|
||||||
|
|
||||||
- The WinFsp API, which is documented in the include file `inc/winfsp/winfsp.h` (and online at http://www.secfs.net/winfsp/apiref/). This API consists of the `FSP_FILE_SYSTEM_INTERFACE` "class" and the `FspFileSystem*` functions.
|
- The WinFsp API, which is documented in the include file `inc/winfsp/winfsp.h` (and online at https://winfsp.dev/apiref). This API consists of the `FSP_FILE_SYSTEM_INTERFACE` "class" and the `FspFileSystem*` functions.
|
||||||
- The FUSE (high-level) API, which is the well understood API from the FUSE project originally by Miklos Szeredi.
|
- The FUSE (high-level) API, which is the well understood API from the FUSE project originally by Miklos Szeredi.
|
||||||
|
|
||||||
Given the similarities between the two API's some questions naturally arise:
|
Given the similarities between the two API's some questions naturally arise:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
= Queued Events - Windows kernel events with IOCP scheduling characteristics
|
= Queued Events - Windows kernel events with IOCP scheduling characteristics
|
||||||
|
|
||||||
In this article I am discussing _Queued Events_. _Queued Events_ are a Windows kernel synchronization mechanism that I invented for https://github.com/billziss-gh/winfsp[WinFsp - FUSE for Windows]. _Queued Events_ behave like kernel Synchronization Events (i.e. Win32 auto-reset events), but provide scheduling characteristics similar to those of I/O Completion Ports.
|
In this article I am discussing _Queued Events_. _Queued Events_ are a Windows kernel synchronization mechanism that I invented for https://github.com/winfsp/winfsp[WinFsp - FUSE for Windows]. _Queued Events_ behave like kernel Synchronization Events (i.e. Win32 auto-reset events), but provide scheduling characteristics similar to those of I/O Completion Ports.
|
||||||
|
|
||||||
== The Problem
|
== The Problem
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ We now have to consider what happens when we have one EventSet concurrently with
|
|||||||
|
|
||||||
NOTE: _Queued Events_ cannot cleanly support an EventClear operation. The obvious choice of using KeRemoveQueue with a 0 timeout is insufficient because it would associate the current thread with the KQUEUE and that is not desirable. KeRundownQueue cannot be used either because it disassociates all threads from the KQUEUE.
|
NOTE: _Queued Events_ cannot cleanly support an EventClear operation. The obvious choice of using KeRemoveQueue with a 0 timeout is insufficient because it would associate the current thread with the KQUEUE and that is not desirable. KeRundownQueue cannot be used either because it disassociates all threads from the KQUEUE.
|
||||||
|
|
||||||
The complete implementation of _Queued Events_ within WinFsp can be found here: https://github.com/billziss-gh/winfsp/blob/v1.1/src/sys/driver.h#L655-L795
|
The complete implementation of _Queued Events_ within WinFsp can be found here: https://github.com/winfsp/winfsp/blob/v1.1/src/sys/driver.h#L655-L795
|
||||||
|
|
||||||
== Queued Events Scheduling Characteristics
|
== Queued Events Scheduling Characteristics
|
||||||
|
|
||||||
@ -102,4 +102,3 @@ Queued Events encapsulate KQUEUE's and therefore inherit their scheduling charac
|
|||||||
- They limit the number of threads that can be satisfied concurrently.
|
- They limit the number of threads that can be satisfied concurrently.
|
||||||
|
|
||||||
These characteristics are desirable because they reduce the number of context switches thus speeding up the WinFsp IPC implementation. Performance testing immediately after the incorporation of _Queued Events_ into WinFsp showed significant performance improvements; profiling with xperf showed that context switches among file system threads were now a relatively rare event!
|
These characteristics are desirable because they reduce the number of context switches thus speeding up the WinFsp IPC implementation. Performance testing immediately after the incorporation of _Queued Events_ into WinFsp showed significant performance improvements; profiling with xperf showed that context switches among file system threads were now a relatively rare event!
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ implib=${prefix}/bin/winfsp-${arch}.dll
|
|||||||
Name: fuse
|
Name: fuse
|
||||||
Description: WinFsp FUSE compatible API
|
Description: WinFsp FUSE compatible API
|
||||||
Version: 2.8
|
Version: 2.8
|
||||||
URL: http://www.secfs.net/winfsp/
|
URL: https://winfsp.dev
|
||||||
Libs: "${implib}"
|
Libs: "${implib}"
|
||||||
Cflags: -I"${incdir}"
|
Cflags: -I"${incdir}"
|
||||||
----
|
----
|
||||||
|
@ -15,9 +15,9 @@ ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_tests.png[]]
|
|||||||
|
|
||||||
== Fsbench
|
== Fsbench
|
||||||
|
|
||||||
All testing was performed using a new performance test suite developed as part of WinFsp, called https://github.com/billziss-gh/winfsp/blob/master/tst/fsbench/fsbench.c[fsbench]. Fsbench was developed because it allows the creation of tests that are important to file system developers; for example, it can answer questions of the type: "how long does it take to delete 1000 files" or "how long does it take to list a directory with 10000 files in it".
|
All testing was performed using a new performance test suite developed as part of WinFsp, called https://github.com/winfsp/winfsp/blob/master/tst/fsbench/fsbench.c[fsbench]. Fsbench was developed because it allows the creation of tests that are important to file system developers; for example, it can answer questions of the type: "how long does it take to delete 1000 files" or "how long does it take to list a directory with 10000 files in it".
|
||||||
|
|
||||||
Fsbench is based on the https://github.com/billziss-gh/winfsp/tree/master/ext/tlib[tlib] library, originally from the *secfs* project. Tlib is usually used to develop regression test suites in C/C++, but can be also used to create performance tests.
|
Fsbench is based on the https://github.com/winfsp/winfsp/tree/master/ext/tlib[tlib] library, originally from the *secfs* project. Tlib is usually used to develop regression test suites in C/C++, but can be also used to create performance tests.
|
||||||
|
|
||||||
Fsbench currently includes the following tests:
|
Fsbench currently includes the following tests:
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ NOTE: The file system that we build in this tutorial is suitable for education p
|
|||||||
|
|
||||||
== Prerequisites
|
== Prerequisites
|
||||||
|
|
||||||
This tutorial assumes that you have WinFsp and Visual Studio 2015 installed. The WinFsp installer can be downloaded from the WinFsp GitHub repository: https://github.com/billziss-gh/winfsp. The Microsoft Visual Studio Community 2015 can be downloaded for free from Microsoft's web site.
|
This tutorial assumes that you have WinFsp and Visual Studio 2015 installed. The WinFsp installer can be downloaded from the WinFsp GitHub repository: https://github.com/winfsp/winfsp. The Microsoft Visual Studio Community 2015 can be downloaded for free from Microsoft's web site.
|
||||||
|
|
||||||
When installing WinFsp make sure to choose "Developer" to ensure that all necessary header and library files are included in the installation.
|
When installing WinFsp make sure to choose "Developer" to ensure that all necessary header and library files are included in the installation.
|
||||||
|
|
||||||
|
@ -103,8 +103,10 @@ struct fuse_operations
|
|||||||
/* _ */ int (*flock)(const char *path, struct fuse_file_info *, int op);
|
/* _ */ int (*flock)(const char *path, struct fuse_file_info *, int op);
|
||||||
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||||
struct fuse_file_info *fi);
|
struct fuse_file_info *fi);
|
||||||
|
/* WinFsp */
|
||||||
|
/* S */ int (*getpath)(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi);
|
||||||
/* OSXFUSE */
|
/* OSXFUSE */
|
||||||
/* _ */ int (*reserved00)();
|
|
||||||
/* _ */ int (*reserved01)();
|
/* _ */ int (*reserved01)();
|
||||||
/* _ */ int (*reserved02)();
|
/* _ */ int (*reserved02)();
|
||||||
/* _ */ int (*statfs_x)(const char *path, struct fuse_statfs *stbuf);
|
/* _ */ int (*statfs_x)(const char *path, struct fuse_statfs *stbuf);
|
||||||
|
@ -222,7 +222,8 @@ enum
|
|||||||
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
||||||
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
||||||
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
||||||
UINT32 KmReservedFlags:2;\
|
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
|
||||||
|
UINT32 KmReservedFlags:1;\
|
||||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||||
|
@ -1750,6 +1750,8 @@ FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
|
|||||||
/*
|
/*
|
||||||
* Directory buffering
|
* Directory buffering
|
||||||
*/
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBufferEx(PVOID* PDirBuffer,
|
||||||
|
BOOLEAN Reset, ULONG CapacityHint, PNTSTATUS PResult);
|
||||||
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
BOOLEAN Reset, PNTSTATUS PResult);
|
BOOLEAN Reset, PNTSTATUS PResult);
|
||||||
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
@ -4,9 +4,9 @@ RELEASE=10
|
|||||||
CATEGORY="Utils"
|
CATEGORY="Utils"
|
||||||
SUMMARY="WinFsp FUSE compatibility layer"
|
SUMMARY="WinFsp FUSE compatibility layer"
|
||||||
DESCRIPTION="Enables FUSE file systems to be run on Cygwin."
|
DESCRIPTION="Enables FUSE file systems to be run on Cygwin."
|
||||||
HOMEPAGE="http://www.secfs.net/winfsp/"
|
HOMEPAGE="https://winfsp.dev"
|
||||||
|
|
||||||
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/billziss-gh/winfsp/archive/master.tar.gz"}
|
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/winfsp/winfsp/archive/master.tar.gz"}
|
||||||
SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
||||||
|
|
||||||
src_compile()
|
src_compile()
|
||||||
|
@ -4,6 +4,6 @@ incdir=${prefix}/include/fuse
|
|||||||
Name: fuse
|
Name: fuse
|
||||||
Description: WinFsp FUSE compatible API
|
Description: WinFsp FUSE compatible API
|
||||||
Version: @Version@
|
Version: @Version@
|
||||||
URL: http://www.secfs.net/winfsp/
|
URL: https://winfsp.dev
|
||||||
Libs: -lfuse-@Version@
|
Libs: -lfuse-@Version@
|
||||||
Cflags: -I"${incdir}" -DCYGFUSE
|
Cflags: -I"${incdir}" -DCYGFUSE
|
||||||
|
@ -4,9 +4,9 @@ RELEASE=2
|
|||||||
CATEGORY="Utils"
|
CATEGORY="Utils"
|
||||||
SUMMARY="WinFsp FUSE3 compatibility layer"
|
SUMMARY="WinFsp FUSE3 compatibility layer"
|
||||||
DESCRIPTION="Enables FUSE3 file systems to be run on Cygwin."
|
DESCRIPTION="Enables FUSE3 file systems to be run on Cygwin."
|
||||||
HOMEPAGE="http://www.secfs.net/winfsp/"
|
HOMEPAGE="https://winfsp.dev"
|
||||||
|
|
||||||
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/billziss-gh/winfsp/archive/master.tar.gz"}
|
SRC_URI=${CYGPORT_SRC_URI:-"https://github.com/winfsp/winfsp/archive/master.tar.gz"}
|
||||||
SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
SRC_DIR=${CYGPORT_SRC_DIR:-winfsp-master}
|
||||||
|
|
||||||
REQUIRES="fuse"
|
REQUIRES="fuse"
|
||||||
|
@ -4,6 +4,6 @@ incdir=${prefix}/include/fuse3
|
|||||||
Name: fuse
|
Name: fuse
|
||||||
Description: WinFsp FUSE3 compatible API
|
Description: WinFsp FUSE3 compatible API
|
||||||
Version: @Version@
|
Version: @Version@
|
||||||
URL: http://www.secfs.net/winfsp/
|
URL: https://winfsp.dev
|
||||||
Libs: -lfuse-@Version@
|
Libs: -lfuse-@Version@
|
||||||
Cflags: -I"${incdir}" -DCYGFUSE
|
Cflags: -I"${incdir}" -DCYGFUSE
|
||||||
|
@ -21,6 +21,11 @@
|
|||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
|
||||||
|
#define FspFileSystemDirectoryBufferLoBound (256)
|
||||||
|
#define FspFileSystemDirectoryBufferHiBound (1024 * 1024)
|
||||||
|
#define FspFileSystemDirectoryBufferLoFactor (4)
|
||||||
|
#define FspFileSystemDirectoryBufferHiFactor (2)
|
||||||
|
|
||||||
#define RETURN(R, B) \
|
#define RETURN(R, B) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@ -32,7 +37,7 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRWLOCK Lock;
|
SRWLOCK Lock;
|
||||||
ULONG Capacity, LoMark, HiMark;
|
ULONG InitialCapacity, Capacity, LoMark, HiMark;
|
||||||
PUINT8 Buffer;
|
PUINT8 Buffer;
|
||||||
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
|
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
|
||||||
|
|
||||||
@ -179,12 +184,15 @@ static VOID FspFileSystemQSortDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l
|
|||||||
{
|
{
|
||||||
while (r > l)
|
while (r > l)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 1
|
||||||
exch(Index[(l + r) / 2], Index[r - 1]);
|
exch(Index[(l + r) / 2], Index[r - 1]);
|
||||||
compexch(Index[l], Index[r - 1]);
|
compexch(Index[l], Index[r - 1]);
|
||||||
compexch(Index[l], Index[r]);
|
compexch(Index[l], Index[r]);
|
||||||
compexch(Index[r - 1], Index[r]);
|
compexch(Index[r - 1], Index[r]);
|
||||||
|
|
||||||
|
if (r - 1 <= l + 1)
|
||||||
|
break;
|
||||||
|
|
||||||
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l + 1, r - 1);
|
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l + 1, r - 1);
|
||||||
#else
|
#else
|
||||||
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l, r);
|
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l, r);
|
||||||
@ -224,8 +232,8 @@ static inline VOID FspFileSystemSortDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BU
|
|||||||
FspFileSystemQSortDirectoryBuffer(Buffer, Index, 0, Count - 1);
|
FspFileSystemQSortDirectoryBuffer(Buffer, Index, 0, Count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBufferEx(PVOID* PDirBuffer,
|
||||||
BOOLEAN Reset, PNTSTATUS PResult)
|
BOOLEAN Reset, ULONG CapacityHint, PNTSTATUS PResult)
|
||||||
{
|
{
|
||||||
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = FspInterlockedLoadPointer(PDirBuffer);
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = FspInterlockedLoadPointer(PDirBuffer);
|
||||||
|
|
||||||
@ -234,10 +242,20 @@ FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
|||||||
static SRWLOCK CreateLock = SRWLOCK_INIT;
|
static SRWLOCK CreateLock = SRWLOCK_INIT;
|
||||||
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *NewDirBuffer;
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *NewDirBuffer;
|
||||||
|
|
||||||
|
/* compute next (or equal) power of 2; ensure fits within bounds */
|
||||||
|
ULONG bitidx;
|
||||||
|
if (_BitScanReverse(&bitidx, CapacityHint - 1))
|
||||||
|
CapacityHint = (1 << (1 + bitidx));
|
||||||
|
CapacityHint = FspFileSystemDirectoryBufferLoBound > CapacityHint ?
|
||||||
|
FspFileSystemDirectoryBufferLoBound : CapacityHint;
|
||||||
|
CapacityHint = FspFileSystemDirectoryBufferHiBound < CapacityHint ?
|
||||||
|
FspFileSystemDirectoryBufferHiBound : CapacityHint;
|
||||||
|
|
||||||
NewDirBuffer = MemAlloc(sizeof *NewDirBuffer);
|
NewDirBuffer = MemAlloc(sizeof *NewDirBuffer);
|
||||||
if (0 == NewDirBuffer)
|
if (0 == NewDirBuffer)
|
||||||
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
memset(NewDirBuffer, 0, sizeof *NewDirBuffer);
|
memset(NewDirBuffer, 0, sizeof *NewDirBuffer);
|
||||||
|
NewDirBuffer->InitialCapacity = CapacityHint;
|
||||||
InitializeSRWLock(&NewDirBuffer->Lock);
|
InitializeSRWLock(&NewDirBuffer->Lock);
|
||||||
AcquireSRWLockExclusive(&NewDirBuffer->Lock);
|
AcquireSRWLockExclusive(&NewDirBuffer->Lock);
|
||||||
|
|
||||||
@ -267,6 +285,12 @@ FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
|||||||
RETURN(STATUS_SUCCESS, FALSE);
|
RETURN(STATUS_SUCCESS, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
|
BOOLEAN Reset, PNTSTATUS PResult)
|
||||||
|
{
|
||||||
|
return FspFileSystemAcquireDirectoryBufferEx(PDirBuffer, Reset, 0, PResult);
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
||||||
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult)
|
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult)
|
||||||
{
|
{
|
||||||
@ -301,7 +325,7 @@ FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
|||||||
|
|
||||||
if (0 == Buffer)
|
if (0 == Buffer)
|
||||||
{
|
{
|
||||||
Buffer = MemAlloc(Capacity = 512);
|
Buffer = MemAlloc(Capacity = DirBuffer->InitialCapacity);
|
||||||
if (0 == Buffer)
|
if (0 == Buffer)
|
||||||
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
|
|
||||||
@ -309,7 +333,9 @@ FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Buffer = MemRealloc(Buffer, Capacity = DirBuffer->Capacity * 2);
|
ULONG Factor = FspFileSystemDirectoryBufferHiBound > DirBuffer->Capacity ?
|
||||||
|
FspFileSystemDirectoryBufferLoFactor : FspFileSystemDirectoryBufferHiFactor;
|
||||||
|
Buffer = MemRealloc(Buffer, Capacity = DirBuffer->Capacity * Factor);
|
||||||
if (0 == Buffer)
|
if (0 == Buffer)
|
||||||
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
|||||||
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
||||||
* that can happen is that the rights get added twice (which is benign).
|
* that can happen is that the rights get added twice (which is benign).
|
||||||
*
|
*
|
||||||
* See https://github.com/billziss-gh/winfsp/issues/62
|
* See https://github.com/winfsp/winfsp/issues/62
|
||||||
*/
|
*/
|
||||||
AccessRights = 0;
|
AccessRights = 0;
|
||||||
}
|
}
|
||||||
|
@ -1142,7 +1142,8 @@ FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
break;
|
break;
|
||||||
case 13/*FileDispositionInformation*/:
|
case 13/*FileDispositionInformation*/:
|
||||||
case 64/*FileDispositionInformationEx*/:
|
case 64/*FileDispositionInformationEx*/:
|
||||||
if (0 == (0x10/*IGNORE_READONLY_ATTRIBUTE*/ & Request->Req.SetInformation.Info.DispositionEx.Flags) &&
|
if (1/*DELETE*/ == (0x11/*DELETE|IGNORE_READONLY_ATTRIBUTE*/ &
|
||||||
|
Request->Req.SetInformation.Info.DispositionEx.Flags) &&
|
||||||
0 != FileSystem->Interface->GetFileInfo)
|
0 != FileSystem->Interface->GetFileInfo)
|
||||||
{
|
{
|
||||||
Result = FileSystem->Interface->GetFileInfo(FileSystem,
|
Result = FileSystem->Interface->GetFileInfo(FileSystem,
|
||||||
|
@ -5,6 +5,6 @@ implib=${prefix}/bin/winfsp-${arch}.dll
|
|||||||
Name: fuse
|
Name: fuse
|
||||||
Description: WinFsp FUSE compatible API
|
Description: WinFsp FUSE compatible API
|
||||||
Version: 2.8
|
Version: 2.8
|
||||||
URL: http://www.secfs.net/winfsp/
|
URL: https://winfsp.dev
|
||||||
Libs: "${implib}"
|
Libs: "${implib}"
|
||||||
Cflags: -I"${incdir}"
|
Cflags: -I"${incdir}"
|
||||||
|
@ -850,6 +850,29 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID fsp_fuse_intf_GetOpenFileInfoPath(
|
||||||
|
struct fuse *f,
|
||||||
|
const char *PosixPath,
|
||||||
|
struct fuse_file_info *fi,
|
||||||
|
FSP_FSCTL_OPEN_FILE_INFO *OpenFileInfo)
|
||||||
|
{
|
||||||
|
char PosixNormalizedName[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
PWSTR NormalizedName;
|
||||||
|
ULONG NormalizedNameSize;
|
||||||
|
|
||||||
|
if (0 == f->ops.getpath(PosixPath, PosixNormalizedName, sizeof PosixNormalizedName, fi) &&
|
||||||
|
NT_SUCCESS(FspPosixMapPosixToWindowsPath(PosixNormalizedName, &NormalizedName)))
|
||||||
|
{
|
||||||
|
NormalizedNameSize = lstrlenW(NormalizedName) * sizeof(WCHAR);
|
||||||
|
if (OpenFileInfo->NormalizedNameSize >= NormalizedNameSize)
|
||||||
|
{
|
||||||
|
OpenFileInfo->NormalizedNameSize = (UINT16)NormalizedNameSize;
|
||||||
|
memcpy(OpenFileInfo->NormalizedName, NormalizedName, NormalizedNameSize);
|
||||||
|
}
|
||||||
|
FspPosixDeletePath(NormalizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
@ -1015,13 +1038,6 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
|
||||||
* NOTE: Originally WinFsp dit not support disabling the cache manager
|
|
||||||
* for an individual file. This is now possible and we should revisit.
|
|
||||||
*
|
|
||||||
* Ignore fuse_file_info::nonseekable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath,
|
||||||
FUSE_FILE_INFO(CreateOptions & FILE_DIRECTORY_FILE, &fi),
|
FUSE_FILE_INFO(CreateOptions & FILE_DIRECTORY_FILE, &fi),
|
||||||
@ -1029,6 +1045,14 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||||
|
* NOTE: Originally WinFsp did not support disabling the cache manager
|
||||||
|
* for an individual file. This is now possible and we should revisit.
|
||||||
|
*
|
||||||
|
* Ignore fuse_file_info::nonseekable.
|
||||||
|
*/
|
||||||
|
|
||||||
*PFileDesc = filedesc;
|
*PFileDesc = filedesc;
|
||||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||||
|
|
||||||
@ -1040,6 +1064,10 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
fsp_fuse_intf_GetOpenFileInfoPath(f, filedesc->PosixPath, -1 != fi.fh ? &fi : 0,
|
||||||
|
FspFileSystemGetOpenFileInfo(FileInfo));
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -1163,10 +1191,9 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache
|
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||||
* WinFsp does not currently support disabling the cache manager
|
* NOTE: Originally WinFsp did not support disabling the cache manager
|
||||||
* for an individual file although it should not be hard to add
|
* for an individual file. This is now possible and we should revisit.
|
||||||
* if required.
|
|
||||||
*
|
*
|
||||||
* Ignore fuse_file_info::nonseekable.
|
* Ignore fuse_file_info::nonseekable.
|
||||||
*/
|
*/
|
||||||
@ -1182,6 +1209,10 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
fsp_fuse_intf_GetOpenFileInfoPath(f, filedesc->PosixPath, -1 != fi.fh ? &fi : 0,
|
||||||
|
FspFileSystemGetOpenFileInfo(FileInfo));
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -2112,6 +2143,10 @@ static NTSTATUS fsp_fuse_intf_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
char PosixPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
char PosixPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
int ParentLength, FSlashLength, PosixNameLength;
|
int ParentLength, FSlashLength, PosixNameLength;
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
|
char PosixNormalizedName[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
PWSTR NormalizedName, NormalizedNameSuffix;
|
||||||
|
ULONG NormalizedNameSize;
|
||||||
|
BOOLEAN Normalized = FALSE;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (!filedesc->IsDirectory || filedesc->IsReparsePoint)
|
if (!filedesc->IsDirectory || filedesc->IsReparsePoint)
|
||||||
@ -2145,13 +2180,33 @@ static NTSTATUS fsp_fuse_intf_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FUSE does not do FileName normalization; so just return the FileName as given to us!
|
|
||||||
*/
|
|
||||||
|
|
||||||
//memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
//memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + lstrlenW(FileName) * sizeof(WCHAR));
|
|
||||||
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
{
|
||||||
|
if (0 == f->ops.getpath(PosixPath, PosixNormalizedName, sizeof PosixNormalizedName, 0) &&
|
||||||
|
NT_SUCCESS(FspPosixMapPosixToWindowsPath(PosixNormalizedName, &NormalizedName)))
|
||||||
|
{
|
||||||
|
NormalizedNameSuffix = NormalizedName;
|
||||||
|
for (PWSTR P = NormalizedNameSuffix; *P; P++)
|
||||||
|
if (L'\\' == *P)
|
||||||
|
NormalizedNameSuffix = P + 1;
|
||||||
|
NormalizedNameSize = lstrlenW(NormalizedNameSuffix) * sizeof(WCHAR);
|
||||||
|
if (f->VolumeParams.MaxComponentLength * sizeof(WCHAR) >= NormalizedNameSize)
|
||||||
|
{
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + NormalizedNameSize);
|
||||||
|
memcpy(DirInfo->FileNameBuf, NormalizedNameSuffix, NormalizedNameSize);
|
||||||
|
Normalized = TRUE;
|
||||||
|
}
|
||||||
|
FspPosixDeletePath(NormalizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Normalized)
|
||||||
|
{
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + lstrlenW(FileName) * sizeof(WCHAR));
|
||||||
|
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
|||||||
context->private_data = f->data = f->ops.init(&conn);
|
context->private_data = f->data = f->ops.init(&conn);
|
||||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||||
if (!f->VolumeParams.CaseSensitiveSearch)
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 == f->ops.getpath)
|
||||||
/*
|
/*
|
||||||
* Disable GetDirInfoByName when file system is case-insensitive.
|
* Disable GetDirInfoByName when file system is case-insensitive and getpath == 0.
|
||||||
* The reason is that Windows always sends us queries with uppercase
|
* The reason is that Windows always sends us queries with uppercase
|
||||||
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
||||||
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
||||||
@ -184,6 +184,8 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
|||||||
f->has_slashdot = 0 == err && 0040000 == (stbuf.st_mode & 0170000);
|
f->has_slashdot = 0 == err && 0040000 == (stbuf.st_mode & 0170000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (0 == (f->conn_want & FSP_FUSE_CAP_DELETE_ACCESS) || 0 == f->ops.access)
|
||||||
|
f->VolumeParams.PostDispositionWhenNecessaryOnly = 1;
|
||||||
if (0 != f->ops.listxattr && 0 != f->ops.getxattr &&
|
if (0 != f->ops.listxattr && 0 != f->ops.getxattr &&
|
||||||
0 != f->ops.setxattr && 0 != f->ops.removexattr)
|
0 != f->ops.setxattr && 0 != f->ops.removexattr)
|
||||||
f->VolumeParams.ExtendedAttributes = 1;
|
f->VolumeParams.ExtendedAttributes = 1;
|
||||||
|
@ -5,6 +5,6 @@ implib=${prefix}/bin/winfsp-${arch}.dll
|
|||||||
Name: fuse3
|
Name: fuse3
|
||||||
Description: WinFsp FUSE3 compatible API
|
Description: WinFsp FUSE3 compatible API
|
||||||
Version: 3.2
|
Version: 3.2
|
||||||
URL: http://www.secfs.net/winfsp/
|
URL: https://winfsp.dev
|
||||||
Libs: "${implib}"
|
Libs: "${implib}"
|
||||||
Cflags: -I"${incdir}"
|
Cflags: -I"${incdir}"
|
||||||
|
@ -9,3 +9,4 @@ EXPORTS
|
|||||||
NPOpenEnum PRIVATE
|
NPOpenEnum PRIVATE
|
||||||
NPEnumResource PRIVATE
|
NPEnumResource PRIVATE
|
||||||
NPCloseEnum PRIVATE
|
NPCloseEnum PRIVATE
|
||||||
|
NPGetUniversalName PRIVATE
|
||||||
|
93
src/dll/np.c
93
src/dll/np.c
@ -863,6 +863,99 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
|||||||
return NpResult;
|
return NpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPGetUniversalName(
|
||||||
|
LPCWSTR lpLocalPath,
|
||||||
|
DWORD dwInfoLevel,
|
||||||
|
LPVOID lpBuffer,
|
||||||
|
LPDWORD lpBufferSize)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
WCHAR LocalNameBuf[3];
|
||||||
|
PCWSTR RemainLocalPath;
|
||||||
|
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
DWORD RemoteNameSize, RemainLocalPathSize, RequiredBufferSize;
|
||||||
|
|
||||||
|
if (UNIVERSAL_NAME_INFO_LEVEL != dwInfoLevel &&
|
||||||
|
REMOTE_NAME_INFO_LEVEL != dwInfoLevel)
|
||||||
|
return WN_BAD_LEVEL;
|
||||||
|
|
||||||
|
if (0 == lpLocalPath ||
|
||||||
|
L'\0' == lpLocalPath[0] ||
|
||||||
|
L':' != lpLocalPath[1] ||
|
||||||
|
(L'\0' != lpLocalPath[2] && L'\\' != lpLocalPath[2]))
|
||||||
|
return WN_BAD_LOCALNAME;
|
||||||
|
|
||||||
|
LocalNameBuf[0] = lpLocalPath[0];
|
||||||
|
LocalNameBuf[1] = L':';
|
||||||
|
LocalNameBuf[2] = L'\0';
|
||||||
|
RemainLocalPath = lpLocalPath + 2;
|
||||||
|
|
||||||
|
RemoteNameSize = sizeof RemoteNameBuf / sizeof(WCHAR);
|
||||||
|
NpResult = NPGetConnection(LocalNameBuf, RemoteNameBuf, &RemoteNameSize);
|
||||||
|
if (WN_SUCCESS != NpResult)
|
||||||
|
return NpResult;
|
||||||
|
|
||||||
|
RemoteNameSize = lstrlenW(RemoteNameBuf) * sizeof(WCHAR);
|
||||||
|
RemainLocalPathSize = lstrlenW(RemainLocalPath) * sizeof(WCHAR) + sizeof(WCHAR)/* term-0 */;
|
||||||
|
|
||||||
|
if (UNIVERSAL_NAME_INFO_LEVEL == dwInfoLevel)
|
||||||
|
{
|
||||||
|
RequiredBufferSize = sizeof(UNIVERSAL_NAME_INFOW) +
|
||||||
|
/* UniversalName */ RemoteNameSize + RemainLocalPathSize;
|
||||||
|
|
||||||
|
if (RequiredBufferSize > *lpBufferSize)
|
||||||
|
{
|
||||||
|
*lpBufferSize = RequiredBufferSize;
|
||||||
|
NpResult = WN_MORE_DATA;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPUNIVERSAL_NAME_INFOW Info = lpBuffer;
|
||||||
|
memset(Info, 0, sizeof *Info);
|
||||||
|
Info->lpUniversalName = (PVOID)(Info + 1);
|
||||||
|
memcpy(Info->lpUniversalName, RemoteNameBuf, RemoteNameSize);
|
||||||
|
memcpy((PUINT8)Info->lpUniversalName + RemoteNameSize, RemainLocalPath,
|
||||||
|
RemainLocalPathSize);
|
||||||
|
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (REMOTE_NAME_INFO_LEVEL == dwInfoLevel)
|
||||||
|
{
|
||||||
|
RequiredBufferSize = sizeof(REMOTE_NAME_INFOW) +
|
||||||
|
/* UniversalName */ RemoteNameSize + RemainLocalPathSize +
|
||||||
|
/* ConnectionName */RemoteNameSize + sizeof(WCHAR) +
|
||||||
|
/* RemainingPath */ RemainLocalPathSize;
|
||||||
|
|
||||||
|
if (RequiredBufferSize > *lpBufferSize)
|
||||||
|
{
|
||||||
|
*lpBufferSize = RequiredBufferSize;
|
||||||
|
NpResult = WN_MORE_DATA;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPREMOTE_NAME_INFOW Info = lpBuffer;
|
||||||
|
memset(Info, 0, sizeof *Info);
|
||||||
|
Info->lpUniversalName = (PVOID)(Info + 1);
|
||||||
|
Info->lpConnectionName = (PVOID)((PUINT8)Info->lpUniversalName +
|
||||||
|
RemoteNameSize + RemainLocalPathSize);
|
||||||
|
Info->lpRemainingPath = (PVOID)((PUINT8)Info->lpConnectionName +
|
||||||
|
RemoteNameSize + sizeof(WCHAR));
|
||||||
|
memcpy(Info->lpUniversalName, RemoteNameBuf, RemoteNameSize);
|
||||||
|
memcpy((PUINT8)Info->lpUniversalName + RemoteNameSize, RemainLocalPath,
|
||||||
|
RemainLocalPathSize);
|
||||||
|
memcpy(Info->lpConnectionName, RemoteNameBuf, RemoteNameSize + sizeof(WCHAR));
|
||||||
|
memcpy(Info->lpRemainingPath, RemainLocalPath, RemainLocalPathSize);
|
||||||
|
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* should not happen! */
|
||||||
|
NpResult = WN_BAD_LEVEL;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
DWORD Signature; /* cheap and cheerful! */
|
DWORD Signature; /* cheap and cheerful! */
|
||||||
|
@ -277,6 +277,11 @@ namespace Fsp
|
|||||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PostCleanupWhenModifiedOnly); }
|
get { return 0 != (_VolumeParams.Flags & VolumeParams.PostCleanupWhenModifiedOnly); }
|
||||||
set { _VolumeParams.Flags |= (value ? VolumeParams.PostCleanupWhenModifiedOnly : 0); }
|
set { _VolumeParams.Flags |= (value ? VolumeParams.PostCleanupWhenModifiedOnly : 0); }
|
||||||
}
|
}
|
||||||
|
public Boolean PostDispositionWhenNecessaryOnly
|
||||||
|
{
|
||||||
|
get { return 0 != (_VolumeParams.Flags & VolumeParams.PostDispositionWhenNecessaryOnly); }
|
||||||
|
set { _VolumeParams.Flags |= (value ? VolumeParams.PostDispositionWhenNecessaryOnly : 0); }
|
||||||
|
}
|
||||||
public Boolean PassQueryDirectoryPattern
|
public Boolean PassQueryDirectoryPattern
|
||||||
{
|
{
|
||||||
get { return 0 != (_VolumeParams.Flags & VolumeParams.PassQueryDirectoryPattern); }
|
get { return 0 != (_VolumeParams.Flags & VolumeParams.PassQueryDirectoryPattern); }
|
||||||
|
@ -56,6 +56,7 @@ namespace Fsp.Interop
|
|||||||
internal const UInt32 WslFeatures = 0x04000000;
|
internal const UInt32 WslFeatures = 0x04000000;
|
||||||
internal const UInt32 RejectIrpPriorToTransact0 = 0x10000000;
|
internal const UInt32 RejectIrpPriorToTransact0 = 0x10000000;
|
||||||
internal const UInt32 SupportsPosixUnlinkRename = 0x20000000;
|
internal const UInt32 SupportsPosixUnlinkRename = 0x20000000;
|
||||||
|
internal const UInt32 PostDispositionWhenNecessaryOnly = 0x40000000;
|
||||||
internal const int PrefixSize = 192;
|
internal const int PrefixSize = 192;
|
||||||
internal const int FileSystemNameSize = 16;
|
internal const int FileSystemNameSize = 16;
|
||||||
|
|
||||||
@ -1436,8 +1437,8 @@ namespace Fsp.Interop
|
|||||||
String RegPath, DllName, DllPath;
|
String RegPath, DllName, DllPath;
|
||||||
SYSTEM_INFO SystemInfo;
|
SYSTEM_INFO SystemInfo;
|
||||||
GetSystemInfo(out SystemInfo);
|
GetSystemInfo(out SystemInfo);
|
||||||
switch ((UInt32)SystemInfo.wProcessorArchitecture)
|
switch ((UInt32)SystemInfo.wProcessorArchitecture)
|
||||||
{
|
{
|
||||||
case SYSTEM_INFO.PROCESSOR_ARCHITECTURE_ARM64:
|
case SYSTEM_INFO.PROCESSOR_ARCHITECTURE_ARM64:
|
||||||
RegPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\" + ProductName;
|
RegPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\" + ProductName;
|
||||||
DllName = ProductFileName + "-a64.dll";
|
DllName = ProductFileName + "-a64.dll";
|
||||||
@ -1451,7 +1452,7 @@ namespace Fsp.Interop
|
|||||||
RegPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\" + ProductName;
|
RegPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\" + ProductName;
|
||||||
DllName = ProductFileName + "-x86.dll";
|
DllName = ProductFileName + "-x86.dll";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
IntPtr Module;
|
IntPtr Module;
|
||||||
Module = LoadLibraryW(DllName);
|
Module = LoadLibraryW(DllName);
|
||||||
if (IntPtr.Zero == Module)
|
if (IntPtr.Zero == Module)
|
||||||
|
@ -66,11 +66,17 @@ BOOLEAN FspFastIoCheckIfPossible(
|
|||||||
PIO_STATUS_BLOCK IoStatus,
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
PDEVICE_OBJECT DeviceObject)
|
PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#else
|
||||||
FSP_ENTER_BOOL(PAGED_CODE());
|
FSP_ENTER_BOOL(PAGED_CODE());
|
||||||
|
|
||||||
Result = FALSE;
|
Result = FALSE;
|
||||||
|
|
||||||
FSP_LEAVE_BOOL("FileObject=%p", FileObject);
|
FSP_LEAVE_BOOL("FileObject=%p", FileObject);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspAcquireFileForNtCreateSection(
|
VOID FspAcquireFileForNtCreateSection(
|
||||||
@ -299,9 +305,16 @@ VOID FspPropagateTopFlags(PIRP Irp, PIRP TopLevelIrp)
|
|||||||
|
|
||||||
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
|
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* FAST I/O only acquires the Main lock.
|
||||||
|
* Other (non-IRP) top levels acquire the Full lock.
|
||||||
|
*/
|
||||||
DEBUGBREAK_EX(iorecu);
|
DEBUGBREAK_EX(iorecu);
|
||||||
|
|
||||||
FspIrpSetTopFlags(Irp, FspFileNodeAcquireFull);
|
FspIrpSetTopFlags(Irp,
|
||||||
|
(PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP == TopLevelIrp ?
|
||||||
|
FspFileNodeAcquireMain :
|
||||||
|
FspFileNodeAcquireFull);
|
||||||
}
|
}
|
||||||
else if ((PIRP)MM_SYSTEM_RANGE_START <= TopLevelIrp && IO_TYPE_IRP == TopLevelIrp->Type)
|
else if ((PIRP)MM_SYSTEM_RANGE_START <= TopLevelIrp && IO_TYPE_IRP == TopLevelIrp->Type)
|
||||||
{
|
{
|
||||||
|
@ -865,6 +865,8 @@ NTSTATUS FspFsvolDirectoryControlPrepare(
|
|||||||
PVOID Address;
|
PVOID Address;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
|
|
||||||
|
ASSERT(FspProcessBufferSizeMax >= Request->Req.QueryDirectory.Length);
|
||||||
|
|
||||||
Result = FspProcessBufferAcquire(Request->Req.QueryDirectory.Length, &Cookie, &Address);
|
Result = FspProcessBufferAcquire(Request->Req.QueryDirectory.Length, &Cookie, &Address);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -89,8 +89,8 @@ NTSTATUS DriverEntry(
|
|||||||
/* setup fast I/O and resource acquisition */
|
/* setup fast I/O and resource acquisition */
|
||||||
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
||||||
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
||||||
//FspFastIoDispatch.FastIoRead = 0;
|
FspFastIoDispatch.FastIoRead = FspFastIoRead;
|
||||||
//FspFastIoDispatch.FastIoWrite = 0;
|
FspFastIoDispatch.FastIoWrite = FspFastIoWrite;
|
||||||
FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo;
|
FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo;
|
||||||
FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo;
|
FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo;
|
||||||
//FspFastIoDispatch.FastIoLock = 0;
|
//FspFastIoDispatch.FastIoLock = 0;
|
||||||
|
@ -304,6 +304,43 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
|||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
return Result
|
return Result
|
||||||
|
#define FSP_ENTER_FIO(...) \
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject; \
|
||||||
|
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||||
|
{ \
|
||||||
|
FsvolDeviceObject = FspMupGetFsvolDeviceObject(FileObject);\
|
||||||
|
if (0 == FsvolDeviceObject) \
|
||||||
|
{ \
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;\
|
||||||
|
IoStatus->Information = 0; \
|
||||||
|
return TRUE; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
FsvolDeviceObject = DeviceObject;\
|
||||||
|
BOOLEAN Result = TRUE; \
|
||||||
|
BOOLEAN fsp_device_deref = FALSE; \
|
||||||
|
FSP_ENTER_(ioentr, __VA_ARGS__); \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
ASSERT(0 == IoGetTopLevelIrp()); \
|
||||||
|
IoSetTopLevelIrp((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP); \
|
||||||
|
if (!FspDeviceReference(FsvolDeviceObject))\
|
||||||
|
{ \
|
||||||
|
IoStatus->Status = STATUS_CANCELLED;\
|
||||||
|
IoStatus->Information = 0; \
|
||||||
|
goto fsp_leave_label; \
|
||||||
|
} \
|
||||||
|
fsp_device_deref = TRUE; \
|
||||||
|
} while (0,0)
|
||||||
|
#define FSP_LEAVE_FIO(fmt, ...) \
|
||||||
|
FSP_LEAVE_( \
|
||||||
|
FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, Result ? "TRUE" : "FALSE");\
|
||||||
|
if (fsp_device_deref) \
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);\
|
||||||
|
IoSetTopLevelIrp(0); \
|
||||||
|
); \
|
||||||
|
return Result
|
||||||
#define FSP_ENTER_BOOL(...) \
|
#define FSP_ENTER_BOOL(...) \
|
||||||
BOOLEAN Result = TRUE; FSP_ENTER_(iocall, __VA_ARGS__)
|
BOOLEAN Result = TRUE; FSP_ENTER_(iocall, __VA_ARGS__)
|
||||||
#define FSP_LEAVE_BOOL(fmt, ...) \
|
#define FSP_LEAVE_BOOL(fmt, ...) \
|
||||||
@ -383,6 +420,8 @@ FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
|||||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||||
|
|
||||||
/* fast I/O and resource acquisition callbacks */
|
/* fast I/O and resource acquisition callbacks */
|
||||||
|
FAST_IO_READ FspFastIoRead;
|
||||||
|
FAST_IO_WRITE FspFastIoWrite;
|
||||||
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
||||||
FAST_IO_QUERY_STANDARD_INFO FspFastIoQueryStandardInfo;
|
FAST_IO_QUERY_STANDARD_INFO FspFastIoQueryStandardInfo;
|
||||||
FAST_IO_QUERY_NETWORK_OPEN_INFO FspFastIoQueryNetworkOpenInfo;
|
FAST_IO_QUERY_NETWORK_OPEN_INFO FspFastIoQueryNetworkOpenInfo;
|
||||||
@ -1088,7 +1127,7 @@ enum
|
|||||||
FspFsvolDeviceSecurityCacheCapacity = 100,
|
FspFsvolDeviceSecurityCacheCapacity = 100,
|
||||||
FspFsvolDeviceSecurityCacheItemSizeMax = 4096,
|
FspFsvolDeviceSecurityCacheItemSizeMax = 4096,
|
||||||
FspFsvolDeviceDirInfoCacheCapacity = 100,
|
FspFsvolDeviceDirInfoCacheCapacity = 100,
|
||||||
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
FspFsvolDeviceDirInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(FspProcessBufferSizeMax, PAGE_SIZE),
|
||||||
FspFsvolDeviceStreamInfoCacheCapacity = 100,
|
FspFsvolDeviceStreamInfoCacheCapacity = 100,
|
||||||
FspFsvolDeviceStreamInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
FspFsvolDeviceStreamInfoCacheItemSizeMax = FSP_FSCTL_ALIGN_UP(16384, PAGE_SIZE),
|
||||||
FspFsvolDeviceEaCacheCapacity = 100,
|
FspFsvolDeviceEaCacheCapacity = 100,
|
||||||
@ -1360,6 +1399,8 @@ NTSTATUS FspMupRegister(
|
|||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
VOID FspMupUnregister(
|
VOID FspMupUnregister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject);
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
|||||||
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
||||||
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
||||||
FileNode->Header.NodeByteSize = sizeof *FileNode;
|
FileNode->Header.NodeByteSize = sizeof *FileNode;
|
||||||
FileNode->Header.IsFastIoPossible = FastIoIsNotPossible;
|
FileNode->Header.IsFastIoPossible = FastIoIsQuestionable;
|
||||||
FileNode->Header.Resource = &NonPaged->Resource;
|
FileNode->Header.Resource = &NonPaged->Resource;
|
||||||
FileNode->Header.PagingIoResource = &NonPaged->PagingIoResource;
|
FileNode->Header.PagingIoResource = &NonPaged->PagingIoResource;
|
||||||
FileNode->Header.ValidDataLength.QuadPart = MAXLONGLONG;
|
FileNode->Header.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||||
|
@ -1435,12 +1435,30 @@ static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline FspFsvolSetDispositionInformationFlags(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
FSP_FILE_NODE *FileNode,
|
||||||
|
FSP_FILE_DESC *FileDesc,
|
||||||
|
UINT32 DispositionFlags)
|
||||||
|
{
|
||||||
|
BOOLEAN Delete = BooleanFlagOn(DispositionFlags, FILE_DISPOSITION_DELETE);
|
||||||
|
|
||||||
|
FspFileNodeSetDeletePending(FileNode, Delete);
|
||||||
|
FileObject->DeletePending = Delete;
|
||||||
|
|
||||||
|
if (!Delete)
|
||||||
|
FileDesc->PosixDelete = FALSE;
|
||||||
|
else if (FlagOn(DispositionFlags, FILE_DISPOSITION_POSIX_SEMANTICS))
|
||||||
|
FileDesc->PosixDelete = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolSetDispositionInformation(
|
static NTSTATUS FspFsvolSetDispositionInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
||||||
UINT32 DispositionFlags;
|
UINT32 DispositionFlags;
|
||||||
@ -1465,7 +1483,7 @@ static NTSTATUS FspFsvolSetDispositionInformation(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.SupportsPosixUnlinkRename)
|
if (!FsvolDeviceExtension->VolumeParams.SupportsPosixUnlinkRename)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
if (sizeof(FILE_DISPOSITION_INFORMATION_EX) > Length)
|
if (sizeof(FILE_DISPOSITION_INFORMATION_EX) > Length)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
@ -1589,6 +1607,28 @@ retry:
|
|||||||
}
|
}
|
||||||
FileDesc->DispositionStatus = STATUS_SUCCESS;
|
FileDesc->DispositionStatus = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (!FileNode->IsDirectory && FsvolDeviceExtension->VolumeParams.PostDispositionWhenNecessaryOnly)
|
||||||
|
{
|
||||||
|
if (FILE_DISPOSITION_DELETE ==
|
||||||
|
(DispositionFlags & (FILE_DISPOSITION_DELETE | FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE)))
|
||||||
|
{
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfoBuf;
|
||||||
|
if (!FspFileNodeTryGetFileInfo(FileNode, &FileInfoBuf))
|
||||||
|
goto slow;
|
||||||
|
if (0 != (FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_READONLY))
|
||||||
|
{
|
||||||
|
Result = STATUS_CANNOT_DELETE;
|
||||||
|
goto unlock_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFsvolSetDispositionInformationFlags(FileObject, FileNode, FileDesc, DispositionFlags);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto unlock_exit;
|
||||||
|
slow:;
|
||||||
|
}
|
||||||
|
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
||||||
FspFsvolSetInformationRequestFini, &Request);
|
FspFsvolSetInformationRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1622,19 +1662,12 @@ static NTSTATUS FspFsvolSetDispositionInformationSuccess(
|
|||||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
UINT32 DispositionFlags = Request->Req.SetInformation.Info.DispositionEx.Flags;
|
UINT32 DispositionFlags = Request->Req.SetInformation.Info.DispositionEx.Flags;
|
||||||
BOOLEAN Delete = BooleanFlagOn(DispositionFlags, FILE_DISPOSITION_DELETE);
|
|
||||||
|
|
||||||
FspFileNodeSetDeletePending(FileNode, Delete);
|
FspFsvolSetDispositionInformationFlags(FileObject, FileNode, FileDesc, DispositionFlags);
|
||||||
FileObject->DeletePending = Delete;
|
|
||||||
|
|
||||||
if (!Delete)
|
|
||||||
FileDesc->PosixDelete = FALSE;
|
|
||||||
else if (FlagOn(DispositionFlags, FILE_DISPOSITION_POSIX_SEMANTICS))
|
|
||||||
FileDesc->PosixDelete = TRUE;
|
|
||||||
|
|
||||||
/* fastfat does this, although it seems unnecessary */
|
/* fastfat does this, although it seems unnecessary */
|
||||||
#if 1
|
#if 1
|
||||||
if (FileNode->IsDirectory && Delete)
|
if (FileNode->IsDirectory && FlagOn(DispositionFlags, FILE_DISPOSITION_DELETE))
|
||||||
{
|
{
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
||||||
|
@ -43,6 +43,8 @@ NTSTATUS FspMupRegister(
|
|||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
VOID FspMupUnregister(
|
VOID FspMupUnregister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject);
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||||
static NTSTATUS FspMupRedirQueryPathEx(
|
static NTSTATUS FspMupRedirQueryPathEx(
|
||||||
@ -52,6 +54,7 @@ static NTSTATUS FspMupRedirQueryPathEx(
|
|||||||
#pragma alloc_text(PAGE, FspMupGetClassName)
|
#pragma alloc_text(PAGE, FspMupGetClassName)
|
||||||
#pragma alloc_text(PAGE, FspMupRegister)
|
#pragma alloc_text(PAGE, FspMupRegister)
|
||||||
#pragma alloc_text(PAGE, FspMupUnregister)
|
#pragma alloc_text(PAGE, FspMupUnregister)
|
||||||
|
#pragma alloc_text(PAGE, FspMupGetFsvolDeviceObject)
|
||||||
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
||||||
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
||||||
#endif
|
#endif
|
||||||
@ -191,6 +194,27 @@ VOID FspMupUnregister(
|
|||||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = 0;
|
||||||
|
|
||||||
|
ASSERT(0 != FileObject);
|
||||||
|
|
||||||
|
if (FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
FsvolDeviceObject = ((FSP_FILE_NODE*)FileObject->FsContext)->FsvolDeviceObject;
|
||||||
|
else if (0 != FileObject->FsContext2 &&
|
||||||
|
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
||||||
|
IO_TYPE_DEVICE == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||||
|
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||||
|
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||||
|
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||||
|
|
||||||
|
return FsvolDeviceObject;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
||||||
{
|
{
|
||||||
@ -276,7 +300,7 @@ NTSTATUS FspMupHandleIrp(
|
|||||||
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
||||||
else if (0 != FileObject->FsContext2 &&
|
else if (0 != FileObject->FsContext2 &&
|
||||||
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
||||||
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
IO_TYPE_DEVICE == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||||
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||||
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||||
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||||
|
103
src/sys/read.c
103
src/sys/read.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
FAST_IO_READ FspFastIoRead;
|
||||||
static NTSTATUS FspFsvolRead(
|
static NTSTATUS FspFsvolRead(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolReadCached(
|
static NTSTATUS FspFsvolReadCached(
|
||||||
@ -35,6 +36,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini;
|
|||||||
FSP_DRIVER_DISPATCH FspRead;
|
FSP_DRIVER_DISPATCH FspRead;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFastIoRead)
|
||||||
#pragma alloc_text(PAGE, FspFsvolRead)
|
#pragma alloc_text(PAGE, FspFsvolRead)
|
||||||
#pragma alloc_text(PAGE, FspFsvolReadCached)
|
#pragma alloc_text(PAGE, FspFsvolReadCached)
|
||||||
#pragma alloc_text(PAGE, FspFsvolReadNonCached)
|
#pragma alloc_text(PAGE, FspFsvolReadNonCached)
|
||||||
@ -55,6 +57,107 @@ enum
|
|||||||
};
|
};
|
||||||
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
|
BOOLEAN FspFastIoRead(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER ByteOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN CanWait,
|
||||||
|
ULONG Key,
|
||||||
|
PVOID UserBuffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_ENTER_FIO(PAGED_CODE());
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
|
||||||
|
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FILE_NODE* FileNode = FileObject->FsContext;
|
||||||
|
LARGE_INTEGER ReadOffset = *ByteOffset;
|
||||||
|
ULONG ReadLength = Length;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
|
||||||
|
/* only regular files can be read */
|
||||||
|
if (FileNode->IsDirectory)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have anything to read? */
|
||||||
|
if (0 == ReadLength)
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
|
||||||
|
/* does the file support caching? */
|
||||||
|
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* try to acquire the FileNode Main shared */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* is the file actually cached? */
|
||||||
|
if (0 == FileObject->PrivateCacheMap)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does the file have oplocks or file locks? */
|
||||||
|
Result =
|
||||||
|
FsRtlOplockIsFastIoPossible(FspFileNodeAddrOfOplock(FileNode)) &&
|
||||||
|
!FsRtlAreThereCurrentFileLocks(&FileNode->FileLock);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trim ReadLength; the cache manager does not tolerate reads beyond file size */
|
||||||
|
ASSERT(FspTimeoutInfinity32 ==
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout);
|
||||||
|
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||||
|
if ((UINT64)ReadOffset.QuadPart >= FileInfo.FileSize)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
IoStatus->Status = STATUS_END_OF_FILE;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
if ((UINT64)ReadLength > FileInfo.FileSize - ReadOffset.QuadPart)
|
||||||
|
ReadLength = (ULONG)(FileInfo.FileSize - ReadOffset.QuadPart);
|
||||||
|
|
||||||
|
NTSTATUS Result0 =
|
||||||
|
FspCcCopyRead(FileObject, &ReadOffset, ReadLength, CanWait, UserBuffer, IoStatus);
|
||||||
|
if (!NT_SUCCESS(Result0))
|
||||||
|
{
|
||||||
|
IoStatus->Status = Result0;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
Result = STATUS_SUCCESS == Result0;
|
||||||
|
|
||||||
|
SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
|
||||||
|
if (Result)
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = ReadOffset.QuadPart + ReadLength;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
FSP_LEAVE_FIO(
|
||||||
|
"FileObject=%p, UserBuffer=%p, CanWait=%d, "
|
||||||
|
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
||||||
|
FileObject, UserBuffer, CanWait,
|
||||||
|
Key, ByteOffset->HighPart, ByteOffset->LowPart, Length);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolRead(
|
static NTSTATUS FspFsvolRead(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
125
src/sys/write.c
125
src/sys/write.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
FAST_IO_WRITE FspFastIoWrite;
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolWriteCached(
|
static NTSTATUS FspFsvolWriteCached(
|
||||||
@ -36,6 +37,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolWriteNonCachedRequestFini;
|
|||||||
FSP_DRIVER_DISPATCH FspWrite;
|
FSP_DRIVER_DISPATCH FspWrite;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFastIoWrite)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWrite)
|
#pragma alloc_text(PAGE, FspFsvolWrite)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
||||||
@ -56,6 +58,129 @@ enum
|
|||||||
};
|
};
|
||||||
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
|
BOOLEAN FspFastIoWrite(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER ByteOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN CanWait,
|
||||||
|
ULONG Key,
|
||||||
|
PVOID UserBuffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_ENTER_FIO(PAGED_CODE());
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
|
||||||
|
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FILE_NODE* FileNode = FileObject->FsContext;
|
||||||
|
LARGE_INTEGER WriteOffset = *ByteOffset;
|
||||||
|
ULONG WriteLength = Length;
|
||||||
|
BOOLEAN WriteToEndOfFile =
|
||||||
|
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
UINT64 WriteEndOffset;
|
||||||
|
BOOLEAN ExtendingFile;
|
||||||
|
|
||||||
|
/* only regular files can be written */
|
||||||
|
if (FileNode->IsDirectory)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have anything to write? */
|
||||||
|
if (0 == WriteLength)
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
|
||||||
|
/* WinFsp cannot do Fast I/O when extending file */
|
||||||
|
if (WriteToEndOfFile)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* does the file support caching? is it write-through? */
|
||||||
|
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) ||
|
||||||
|
FlagOn(FileObject->Flags, FO_WRITE_THROUGH))
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* can we write without flushing? */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
CcCanIWrite(FileObject, WriteLength, CanWait, FALSE) &&
|
||||||
|
CcCopyWriteWontFlush(FileObject, &WriteOffset, WriteLength);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* try to acquire the FileNode Main exclusive */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* is the file actually cached? */
|
||||||
|
if (0 == FileObject->PrivateCacheMap)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does the file have oplocks or file locks? */
|
||||||
|
Result =
|
||||||
|
FsRtlOplockIsFastIoPossible(FspFileNodeAddrOfOplock(FileNode)) &&
|
||||||
|
!FsRtlAreThereCurrentFileLocks(&FileNode->FileLock);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute new file size */
|
||||||
|
ASSERT(FspTimeoutInfinity32 ==
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout);
|
||||||
|
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||||
|
if (WriteToEndOfFile)
|
||||||
|
WriteOffset.QuadPart = FileInfo.FileSize;
|
||||||
|
WriteEndOffset = WriteOffset.QuadPart + WriteLength;
|
||||||
|
ExtendingFile = FileInfo.FileSize < WriteEndOffset;
|
||||||
|
|
||||||
|
/* WinFsp cannot do Fast I/O when extending file */
|
||||||
|
if (ExtendingFile)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS Result0 =
|
||||||
|
FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait, UserBuffer);
|
||||||
|
if (!NT_SUCCESS(Result0))
|
||||||
|
{
|
||||||
|
IoStatus->Status = Result0;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
Result = STATUS_SUCCESS == Result0;
|
||||||
|
|
||||||
|
if (Result)
|
||||||
|
{
|
||||||
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = WriteEndOffset;
|
||||||
|
IoStatus->Information = WriteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
FSP_LEAVE_FIO(
|
||||||
|
"FileObject=%p, UserBuffer=%p, CanWait=%d, "
|
||||||
|
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
||||||
|
FileObject, UserBuffer, CanWait,
|
||||||
|
Key, ByteOffset->HighPart, ByteOffset->LowPart, Length);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
@ -6,8 +6,8 @@ setlocal EnableDelayedExpansion
|
|||||||
call "%~dp0myinfo.bat"
|
call "%~dp0myinfo.bat"
|
||||||
|
|
||||||
set MsiName="%MyProductName% - %MyDescription%"
|
set MsiName="%MyProductName% - %MyDescription%"
|
||||||
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
set CrossCert="%~dp0%MyCrossCert%"
|
||||||
set Issuer="DigiCert"
|
set Issuer="%MyCertIssuer%"
|
||||||
set Subject="%MyCompanyName%"
|
set Subject="%MyCompanyName%"
|
||||||
|
|
||||||
set Configuration=Release
|
set Configuration=Release
|
||||||
@ -24,6 +24,19 @@ if X%~nx0==Xbuild-choco.bat (
|
|||||||
goto :choco
|
goto :choco
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set BuildArm64=yes
|
||||||
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||||
|
set BuildArm64=no
|
||||||
|
)
|
||||||
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||||
|
set BuildArm64=no
|
||||||
|
)
|
||||||
|
if X%BuildArm64%==Xno (
|
||||||
|
echo WARNING: APPVEYOR BUILD ON UNSUPPORTED VERSION OF VISUAL STUDIO.
|
||||||
|
echo WARNING: ARM64 BUILD PRODUCTS ARE COPIES OF X64 BUILD PRODUCTS.
|
||||||
|
echo:
|
||||||
|
)
|
||||||
|
|
||||||
call "%~dp0vcvarsall.bat" x64
|
call "%~dp0vcvarsall.bat" x64
|
||||||
|
|
||||||
if not X%SignedPackage%==X (
|
if not X%SignedPackage%==X (
|
||||||
@ -44,12 +57,20 @@ if X%SignedPackage%==X (
|
|||||||
if exist "%%d" rmdir /s/q "%%d"
|
if exist "%%d" rmdir /s/q "%%d"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if X%BuildArm64%==Xyes (
|
||||||
|
devenv winfsp.sln /build "%Configuration%|ARM64"
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
)
|
||||||
devenv winfsp.sln /build "%Configuration%|x64"
|
devenv winfsp.sln /build "%Configuration%|x64"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
devenv winfsp.sln /build "%Configuration%|x86"
|
devenv winfsp.sln /build "%Configuration%|x86"
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto fail
|
||||||
|
if X%BuildArm64%==Xno (
|
||||||
|
copy build\%Configuration%\*-x64.* build\%Configuration%\*-a64.* >nul
|
||||||
|
if errorlevel 1 goto fail
|
||||||
|
)
|
||||||
|
|
||||||
for %%f in (build\%Configuration%\%MyProductFileName%-x64.sys build\%Configuration%\%MyProductFileName%-x86.sys) do (
|
for %%f in (build\%Configuration%\%MyProductFileName%-a64.sys build\%Configuration%\%MyProductFileName%-x64.sys build\%Configuration%\%MyProductFileName%-x86.sys) do (
|
||||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com %%f
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com %%f
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 %%f
|
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 %%f
|
||||||
@ -69,6 +90,9 @@ if X%SignedPackage%==X (
|
|||||||
echo .Set Compress=on >>driver.ddf
|
echo .Set Compress=on >>driver.ddf
|
||||||
echo .Set CabinetNameTemplate=driver.cab >>driver.ddf
|
echo .Set CabinetNameTemplate=driver.cab >>driver.ddf
|
||||||
echo .Set DiskDirectory1=. >>driver.ddf
|
echo .Set DiskDirectory1=. >>driver.ddf
|
||||||
|
echo .Set DestinationDir=a64 >>driver.ddf
|
||||||
|
echo driver-a64.inf >>driver.ddf
|
||||||
|
echo %MyProductFileName%-a64.sys >>driver.ddf
|
||||||
echo .Set DestinationDir=x64 >>driver.ddf
|
echo .Set DestinationDir=x64 >>driver.ddf
|
||||||
echo driver-x64.inf >>driver.ddf
|
echo driver-x64.inf >>driver.ddf
|
||||||
echo %MyProductFileName%-x64.sys >>driver.ddf
|
echo %MyProductFileName%-x64.sys >>driver.ddf
|
||||||
@ -76,7 +100,7 @@ if X%SignedPackage%==X (
|
|||||||
echo driver-x86.inf >>driver.ddf
|
echo driver-x86.inf >>driver.ddf
|
||||||
echo %MyProductFileName%-x86.sys >>driver.ddf
|
echo %MyProductFileName%-x86.sys >>driver.ddf
|
||||||
makecab /F driver.ddf
|
makecab /F driver.ddf
|
||||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /t http://timestamp.digicert.com driver.cab
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 driver.cab
|
||||||
if errorlevel 1 set /a signfail=signfail+1
|
if errorlevel 1 set /a signfail=signfail+1
|
||||||
popd
|
popd
|
||||||
)
|
)
|
||||||
|
@ -6,8 +6,8 @@ setlocal EnableDelayedExpansion
|
|||||||
call "%~dp0myinfo.bat"
|
call "%~dp0myinfo.bat"
|
||||||
|
|
||||||
set MsiName="%MyProductName% - %MyDescription%"
|
set MsiName="%MyProductName% - %MyDescription%"
|
||||||
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
set CrossCert="%~dp0%MyCrossCert%"
|
||||||
set Issuer="DigiCert"
|
set Issuer="%MyCertIssuer%"
|
||||||
set Subject="%MyCompanyName%"
|
set Subject="%MyCompanyName%"
|
||||||
|
|
||||||
set Configuration=Release
|
set Configuration=Release
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
REM This script is used to fix GitHub issue #162:
|
REM This script is used to fix GitHub issue #162:
|
||||||
REM https://github.com/billziss-gh/winfsp/issues/162
|
REM https://github.com/winfsp/winfsp/issues/162
|
||||||
REM
|
REM
|
||||||
REM It works as follows:
|
REM It works as follows:
|
||||||
REM
|
REM
|
||||||
|
@ -14,6 +14,10 @@ for /F "tokens=2,3,4 delims=<>" %%a in (%~dp0..\build\VStudio\build.version.prop
|
|||||||
set MyProductVersion=%%b
|
set MyProductVersion=%%b
|
||||||
) else if "%%a"=="MyProductStage" (
|
) else if "%%a"=="MyProductStage" (
|
||||||
set MyProductStage=%%b
|
set MyProductStage=%%b
|
||||||
|
) else if "%%a"=="MyCrossCert" (
|
||||||
|
set MyCrossCert=%%b
|
||||||
|
) else if "%%a"=="MyCertIssuer" (
|
||||||
|
set MyCertIssuer=%%b
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -24,3 +28,5 @@ echo MyDescription=%MyDescription%
|
|||||||
echo MyCompanyName=%MyCompanyName%
|
echo MyCompanyName=%MyCompanyName%
|
||||||
echo MyProductVersion=%MyProductVersion%
|
echo MyProductVersion=%MyProductVersion%
|
||||||
echo MyProductStage=%MyProductStage%
|
echo MyProductStage=%MyProductStage%
|
||||||
|
echo MyCrossCert=%MyCrossCert%
|
||||||
|
echo MyCertIssuer=%MyCertIssuer%
|
||||||
|
63
tools/run-all-perf-tests.bat
Normal file
63
tools/run-all-perf-tests.bat
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
REM see https://stackoverflow.com/a/11995662
|
||||||
|
net session >nul 2>&1
|
||||||
|
if !ERRORLEVEL! neq 0 echo must be run as Administrator >&2 & goto fail
|
||||||
|
|
||||||
|
set Count=3
|
||||||
|
if not X%1==X set Count=%1
|
||||||
|
|
||||||
|
set outdir=%cd%
|
||||||
|
pushd %~dp0..
|
||||||
|
set ProjRoot=%cd%
|
||||||
|
popd
|
||||||
|
|
||||||
|
set perftests="%ProjRoot%\tools\run-perf-tests.bat"
|
||||||
|
set memfs="%ProjRoot%\build\VStudio\build\Release\memfs-x64.exe"
|
||||||
|
set ntptfs="%ProjRoot%\tst\ntptfs\build\Release\ntptfs-x64.exe"
|
||||||
|
if not exist %memfs% echo cannot find memfs >&2 & goto fail
|
||||||
|
if not exist %ntptfs% echo cannot find ntptfs >&2 & goto fail
|
||||||
|
|
||||||
|
mkdir C:\t
|
||||||
|
pushd C:\t
|
||||||
|
for /l %%i in (1,1,%Count%) do (
|
||||||
|
echo ntfs-%%i
|
||||||
|
call %perftests% Release > %outdir%\ntfs-%%i.csv
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
rmdir C:\t
|
||||||
|
|
||||||
|
start "" /b %memfs% -t -1 -n 1000000 -i -m X:
|
||||||
|
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||||
|
pushd X:\
|
||||||
|
for /l %%i in (1,1,%Count%) do (
|
||||||
|
echo memfs-%%i
|
||||||
|
call %perftests% Release > %outdir%\memfs-%%i.csv
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
taskkill /f /im memfs-x64.exe
|
||||||
|
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "Add-MpPreference -ExclusionProcess '%ntptfs%'"
|
||||||
|
mkdir C:\t
|
||||||
|
start "" /b %ntptfs% -t -1 -p C:\t -m X:
|
||||||
|
waitfor 7BF47D72F6664550B03248ECFE77C7DD /t 3 2>nul
|
||||||
|
pushd X:\
|
||||||
|
for /l %%i in (1,1,%Count%) do (
|
||||||
|
echo ntptfs-%%i
|
||||||
|
call %perftests% Release > %outdir%\ntptfs-%%i.csv
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
|
popd
|
||||||
|
taskkill /f /im ntptfs-x64.exe
|
||||||
|
rmdir C:\t
|
||||||
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "Remove-MpPreference -ExclusionProcess '%ntptfs%'"
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
@ -762,6 +762,9 @@ rem difference.
|
|||||||
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||||
call :__ifstest %1 /g ReparsePoints -t SetPointEASNotSupportedTest -t EnumReparsePointsTest -t ChangeNotificationReparseTest /c
|
call :__ifstest %1 /g ReparsePoints -t SetPointEASNotSupportedTest -t EnumReparsePointsTest -t ChangeNotificationReparseTest /c
|
||||||
if !ERRORLEVEL! neq 0 set IfsTestNtptfsExit=1
|
if !ERRORLEVEL! neq 0 set IfsTestNtptfsExit=1
|
||||||
|
) else if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||||
|
call :__ifstest %1 /g ReparsePoints -t SetPointEASNotSupportedTest -t EnumReparsePointsTest -t ChangeNotificationReparseTest -t SetPointIoReparseDataInvalidTest -t SetPointIoReparseTagMismatchTest -t SetPointAttributeConflictTest /c
|
||||||
|
if !ERRORLEVEL! neq 0 set IfsTestNtptfsExit=1
|
||||||
) else (
|
) else (
|
||||||
call :__ifstest %1 /g ReparsePoints -t SetPointEASNotSupportedTest -t EnumReparsePointsTest -t ChangeNotificationReparseTest -t SetPointIoReparseDataInvalidTest /c
|
call :__ifstest %1 /g ReparsePoints -t SetPointEASNotSupportedTest -t EnumReparsePointsTest -t ChangeNotificationReparseTest -t SetPointIoReparseDataInvalidTest /c
|
||||||
if !ERRORLEVEL! neq 0 set IfsTestNtptfsExit=1
|
if !ERRORLEVEL! neq 0 set IfsTestNtptfsExit=1
|
||||||
@ -845,17 +848,45 @@ if not X!IfsTestFound!==XYES set IfsTestExit=1
|
|||||||
exit /b !IfsTestExit!
|
exit /b !IfsTestExit!
|
||||||
|
|
||||||
:sample-ntptfs-x64
|
:sample-ntptfs-x64
|
||||||
call :__run_sample_ntptfs_test ntptfs x64 ntptfs-x64 ^
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" ^
|
rem need POSIX delete for rename_mmap_test
|
||||||
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
call :__run_sample_ntptfs_test ntptfs x64 ntptfs-x64 ^
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
) else if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||||
|
rem need POSIX delete for rename_mmap_test
|
||||||
|
call :__run_sample_ntptfs_test ntptfs x64 ntptfs-x64 ^
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
) else (
|
||||||
|
call :__run_sample_ntptfs_test ntptfs x64 ntptfs-x64 ^
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x64.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:sample-ntptfs-x86
|
:sample-ntptfs-x86
|
||||||
call :__run_sample_ntptfs_test ntptfs x86 ntptfs-x86 ^
|
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||||
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" ^
|
rem need POSIX delete for rename_mmap_test
|
||||||
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
call :__run_sample_ntptfs_test ntptfs x86 ntptfs-x86 ^
|
||||||
if !ERRORLEVEL! neq 0 goto fail
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
) else if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||||
|
rem need POSIX delete for rename_mmap_test
|
||||||
|
call :__run_sample_ntptfs_test ntptfs x86 ntptfs-x86 ^
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -rename_mmap_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
) else (
|
||||||
|
call :__run_sample_ntptfs_test ntptfs x86 ntptfs-x86 ^
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\winfsp-tests-x86.exe" ^
|
||||||
|
"--external --resilient +* -rename_flipflop_test -exec_rename_dir_test -stream_rename_flipflop_test"
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:sample-ntptfs-x64-fsx
|
:sample-ntptfs-x64-fsx
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
set vcvarsall="%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
|
set vcvarsall=""
|
||||||
|
|
||||||
set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||||
if exist %vswhere% (
|
if exist %vswhere% (
|
||||||
for /f "usebackq tokens=*" %%i in (`%vswhere% -latest -find VC\**\vcvarsall.bat`) do (
|
for /f "usebackq tokens=*" %%i in (`%vswhere% -version [15.0^,17.0^) -find VC\**\vcvarsall.bat`) do (
|
||||||
if exist "%%i" (
|
set vcvarsall="%%i"
|
||||||
set vcvarsall="%%i"
|
)
|
||||||
) else (
|
)
|
||||||
for /f "usebackq tokens=*" %%i in (`%vswhere% -latest -property installationPath`) do (
|
|
||||||
set vcvarsall="%%i\VC\Auxiliary\Build\vcvarsall.bat"
|
if not exist %vcvarsall% (
|
||||||
)
|
if exist %vswhere% (
|
||||||
|
for /f "usebackq tokens=*" %%i in (`%vswhere% -version [15.0^,17.0^) -property installationPath`) do (
|
||||||
|
set vcvarsall="%%i\VC\Auxiliary\Build\vcvarsall.bat"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not exist %vcvarsall% (
|
||||||
|
set vcvarsall="%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
|
||||||
|
)
|
||||||
|
|
||||||
call %vcvarsall% %*
|
call %vcvarsall% %*
|
||||||
|
60
tools/winfsp-winpe.bat
Normal file
60
tools/winfsp-winpe.bat
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
if NOT [%1]==[] set Arch=%1
|
||||||
|
if NOT [%2]==[] set Mount=%2
|
||||||
|
if NOT [%3]==[] set Image=%3
|
||||||
|
if [!Mount!]==[] (echo usage: winfsp-winpe Arch Mount [Image] >&2 & goto fail)
|
||||||
|
|
||||||
|
set SkipDism=0
|
||||||
|
if [!Image!]==[] set SkipDism=1
|
||||||
|
|
||||||
|
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||||
|
set RegVal="InstallDir"
|
||||||
|
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||||
|
if !ERRORLEVEL! equ 0 (
|
||||||
|
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||||
|
set InstallDir=%%j
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not exist "!InstallDir!" (echo cannot find WinFsp installation >&2 & goto fail)
|
||||||
|
|
||||||
|
if not exist !Mount! (echo cannot find mount directory !Mount! >&2 & goto fail)
|
||||||
|
if !SkipDism! equ 0 (
|
||||||
|
if not exist !Image! (echo cannot find image file !Image! >&2 & goto fail)
|
||||||
|
)
|
||||||
|
|
||||||
|
if !SkipDism! equ 0 (
|
||||||
|
echo Dism /Mount-Image /ImageFile:!Image! /Index:1 /MountDir:!Mount!
|
||||||
|
Dism /Mount-Image /ImageFile:!Image! /Index:1 /MountDir:!Mount!
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
|
|
||||||
|
echo copy "!InstallDir!"\bin\winfsp-!Arch!.dll !Mount!\Windows\System32
|
||||||
|
copy "!InstallDir!"\bin\winfsp-!Arch!.dll !Mount!\Windows\System32 >nul
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
|
||||||
|
echo copy "!InstallDir!"\bin\winfsp-!Arch!.sys !Mount!\Windows\System32
|
||||||
|
copy "!InstallDir!"\bin\winfsp-!Arch!.sys !Mount!\Windows\System32 >nul
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
|
||||||
|
rem echo copy "!InstallDir!"\bin\memfs-!Arch!.exe !Mount!\Windows\System32
|
||||||
|
rem copy "!InstallDir!"\bin\memfs-!Arch!.exe !Mount!\Windows\System32 >nul
|
||||||
|
rem if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
|
||||||
|
echo Creating !Mount!\Windows\System32\startnet.cmd
|
||||||
|
echo regsvr32 /s winfsp-x64.dll > !Mount!\Windows\System32\startnet.cmd
|
||||||
|
echo wpeinit >> !Mount!\Windows\System32\startnet.cmd
|
||||||
|
|
||||||
|
if !SkipDism! equ 0 (
|
||||||
|
echo Dism /Unmount-Image /MountDir:!Mount! /Commit
|
||||||
|
Dism /Unmount-Image /MountDir:!Mount! /Commit
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
)
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
38
tools/wpr-test.bat
Normal file
38
tools/wpr-test.bat
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
if not X%1==X set File=%1
|
||||||
|
if X%File%==X (echo usage: wpr-test file.etl fsbench-args... >&2 & goto fail)
|
||||||
|
|
||||||
|
REM see https://stackoverflow.com/a/45969239/429091
|
||||||
|
set Args=%*
|
||||||
|
call set Args=%%args:*%1=%%
|
||||||
|
|
||||||
|
REM see https://stackoverflow.com/a/11995662
|
||||||
|
net session >nul 2>&1
|
||||||
|
if %ERRORLEVEL% neq 0 echo must be run as Administrator >&2 & goto fail
|
||||||
|
|
||||||
|
set outdir=%cd%
|
||||||
|
pushd %~dp0..
|
||||||
|
set ProjRoot=%cd%
|
||||||
|
popd
|
||||||
|
|
||||||
|
set fsbench="%ProjRoot%\build\VStudio\build\Release\fsbench-x64.exe"
|
||||||
|
if not exist %fsbench% echo cannot find fsbench >&2 & goto fail
|
||||||
|
|
||||||
|
wpr -start CPU -start FileIO
|
||||||
|
|
||||||
|
mkdir fsbench
|
||||||
|
pushd fsbench
|
||||||
|
%fsbench% %Args%
|
||||||
|
popd
|
||||||
|
rmdir fsbench
|
||||||
|
|
||||||
|
wpr -stop %File% %File% -skipPdbGen
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:fail
|
||||||
|
exit /b 1
|
@ -282,6 +282,7 @@ namespace memfs
|
|||||||
Host.ReparsePointsAccessCheck = false;
|
Host.ReparsePointsAccessCheck = false;
|
||||||
Host.NamedStreams = true;
|
Host.NamedStreams = true;
|
||||||
Host.PostCleanupWhenModifiedOnly = true;
|
Host.PostCleanupWhenModifiedOnly = true;
|
||||||
|
Host.PostDispositionWhenNecessaryOnly = true;
|
||||||
Host.PassQueryDirectoryFileName = true;
|
Host.PassQueryDirectoryFileName = true;
|
||||||
Host.ExtendedAttributes = true;
|
Host.ExtendedAttributes = true;
|
||||||
Host.WslFeatures = true;
|
Host.WslFeatures = true;
|
||||||
|
@ -2386,6 +2386,7 @@ NTSTATUS MemfsCreateFunnel(
|
|||||||
VolumeParams.NamedStreams = 1;
|
VolumeParams.NamedStreams = 1;
|
||||||
#endif
|
#endif
|
||||||
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
||||||
|
VolumeParams.PostDispositionWhenNecessaryOnly = 1;
|
||||||
#if defined(MEMFS_DIRINFO_BY_NAME)
|
#if defined(MEMFS_DIRINFO_BY_NAME)
|
||||||
VolumeParams.PassQueryDirectoryFileName = 1;
|
VolumeParams.PassQueryDirectoryFileName = 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,12 +24,14 @@
|
|||||||
#define FileSystemContext ((PTFS *)(FileSystem)->UserContext)
|
#define FileSystemContext ((PTFS *)(FileSystem)->UserContext)
|
||||||
#define FileContextHandle (((FILE_CONTEXT *)(FileContext))->Handle)
|
#define FileContextHandle (((FILE_CONTEXT *)(FileContext))->Handle)
|
||||||
#define FileContextIsDirectory (((FILE_CONTEXT *)(FileContext))->IsDirectory)
|
#define FileContextIsDirectory (((FILE_CONTEXT *)(FileContext))->IsDirectory)
|
||||||
|
#define FileContextDirFileSize (((FILE_CONTEXT *)(FileContext))->DirFileSize)
|
||||||
#define FileContextDirBuffer (&((FILE_CONTEXT *)(FileContext))->DirBuffer)
|
#define FileContextDirBuffer (&((FILE_CONTEXT *)(FileContext))->DirBuffer)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
BOOLEAN IsDirectory;
|
BOOLEAN IsDirectory;
|
||||||
|
ULONG DirFileSize;
|
||||||
PVOID DirBuffer;
|
PVOID DirBuffer;
|
||||||
} FILE_CONTEXT;
|
} FILE_CONTEXT;
|
||||||
|
|
||||||
@ -241,6 +243,7 @@ static NTSTATUS CreateEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memset(FileContext, 0, sizeof *FileContext);
|
memset(FileContext, 0, sizeof *FileContext);
|
||||||
FileContext->Handle = Handle;
|
FileContext->Handle = Handle;
|
||||||
FileContext->IsDirectory = IsDirectory;
|
FileContext->IsDirectory = IsDirectory;
|
||||||
|
FileContext->DirFileSize = (ULONG)FileInfo->FileSize;
|
||||||
*PFileContext = FileContext;
|
*PFileContext = FileContext;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -331,6 +334,7 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
memset(FileContext, 0, sizeof *FileContext);
|
memset(FileContext, 0, sizeof *FileContext);
|
||||||
FileContext->Handle = Handle;
|
FileContext->Handle = Handle;
|
||||||
FileContext->IsDirectory = IsDirectory;
|
FileContext->IsDirectory = IsDirectory;
|
||||||
|
FileContext->DirFileSize = (ULONG)FileInfo->FileSize;
|
||||||
*PFileContext = FileContext;
|
*PFileContext = FileContext;
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
@ -787,6 +791,18 @@ static NTSTATUS BufferedReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
PTFS *Ptfs = FileSystemContext;
|
PTFS *Ptfs = FileSystemContext;
|
||||||
HANDLE Handle = FileContextHandle;
|
HANDLE Handle = FileContextHandle;
|
||||||
|
ULONG CapacityHint = FileContextDirFileSize;
|
||||||
|
/*
|
||||||
|
* An analysis of the relationship between the required buffer capacity and the
|
||||||
|
* NTFS directory size (as reported by FileStandardInformation) showed the ratio
|
||||||
|
* between the two to be between 0.5 and 1 with some outliers outside those bounds.
|
||||||
|
* (For this analysis file names of average length of 4 or 24 were used and NTFS
|
||||||
|
* had 8.3 file names disabled.)
|
||||||
|
*
|
||||||
|
* We use the NTFS directory size as our capacity hint (i.e. ratio of 1), which
|
||||||
|
* means that we may overestimate the required buffer capacity in most cases.
|
||||||
|
* This is ok since our goal is to improve performance.
|
||||||
|
*/
|
||||||
PVOID PDirBuffer = FileContextDirBuffer;
|
PVOID PDirBuffer = FileContextDirBuffer;
|
||||||
BOOLEAN RestartScan;
|
BOOLEAN RestartScan;
|
||||||
ULONG BytesTransferred;
|
ULONG BytesTransferred;
|
||||||
@ -801,7 +817,7 @@ static NTSTATUS BufferedReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
NTSTATUS Result, DirBufferResult;
|
NTSTATUS Result, DirBufferResult;
|
||||||
|
|
||||||
DirBufferResult = STATUS_SUCCESS;
|
DirBufferResult = STATUS_SUCCESS;
|
||||||
if (FspFileSystemAcquireDirectoryBuffer(PDirBuffer, 0 == Marker, &DirBufferResult))
|
if (FspFileSystemAcquireDirectoryBufferEx(PDirBuffer, 0 == Marker, CapacityHint, &DirBufferResult))
|
||||||
{
|
{
|
||||||
for (RestartScan = TRUE;; RestartScan = FALSE)
|
for (RestartScan = TRUE;; RestartScan = FALSE)
|
||||||
{
|
{
|
||||||
@ -1263,6 +1279,7 @@ NTSTATUS PtfsCreate(
|
|||||||
/*FILE_SUPPORTS_POSIX_UNLINK_RENAME*/);
|
/*FILE_SUPPORTS_POSIX_UNLINK_RENAME*/);
|
||||||
VolumeParams.ReadOnlyVolume = !!(FsAttrInfo.V.FileSystemAttributes & FILE_READ_ONLY_VOLUME);
|
VolumeParams.ReadOnlyVolume = !!(FsAttrInfo.V.FileSystemAttributes & FILE_READ_ONLY_VOLUME);
|
||||||
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
VolumeParams.PostCleanupWhenModifiedOnly = 1;
|
||||||
|
VolumeParams.PostDispositionWhenNecessaryOnly = 1;
|
||||||
VolumeParams.PassQueryDirectoryPattern = 1;
|
VolumeParams.PassQueryDirectoryPattern = 1;
|
||||||
VolumeParams.FlushAndPurgeOnCleanup = !!(FsAttributeMask & PtfsFlushAndPurgeOnCleanup);
|
VolumeParams.FlushAndPurgeOnCleanup = !!(FsAttributeMask & PtfsFlushAndPurgeOnCleanup);
|
||||||
VolumeParams.WslFeatures = !!(FsAttributeMask & PtfsWslFeatures);
|
VolumeParams.WslFeatures = !!(FsAttributeMask & PtfsWslFeatures);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <fuse.h>
|
#include <fuse.h>
|
||||||
|
|
||||||
@ -59,6 +60,7 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *rootdir;
|
const char *rootdir;
|
||||||
|
size_t rootlen;
|
||||||
} PTFS;
|
} PTFS;
|
||||||
|
|
||||||
static int ptfs_getattr(const char *path, struct fuse_stat *stbuf)
|
static int ptfs_getattr(const char *path, struct fuse_stat *stbuf)
|
||||||
@ -293,6 +295,43 @@ static int ptfs_utimens(const char *path, const struct fuse_timespec tv[2])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
static int ptfs_getpath(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
if (0 == fi)
|
||||||
|
{
|
||||||
|
ptfs_impl_fullpath(path);
|
||||||
|
|
||||||
|
if (-1 == getpath(path, buf, size))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd = fi_fd(fi);
|
||||||
|
|
||||||
|
if (-1 == fgetpath(fd, buf, size))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTFS *ptfs = fuse_get_context()->private_data;
|
||||||
|
size = strlen(buf);
|
||||||
|
if (size > ptfs->rootlen)
|
||||||
|
{
|
||||||
|
size -= ptfs->rootlen;
|
||||||
|
memmove(buf, buf + ptfs->rootlen, size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf[0] = '/';
|
||||||
|
buf[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(_WIN32)
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
static int ptfs_setcrtime(const char *path, const struct fuse_timespec *tv)
|
static int ptfs_setcrtime(const char *path, const struct fuse_timespec *tv)
|
||||||
{
|
{
|
||||||
@ -344,6 +383,9 @@ static struct fuse_operations ptfs_ops =
|
|||||||
#if defined(PTFS_UTIMENS)
|
#if defined(PTFS_UTIMENS)
|
||||||
.utimens = ptfs_utimens,
|
.utimens = ptfs_utimens,
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
.getpath = ptfs_getpath,
|
||||||
|
#endif
|
||||||
#if defined(_WIN64) || defined(_WIN32)
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
.setcrtime = ptfs_setcrtime,
|
.setcrtime = ptfs_setcrtime,
|
||||||
#endif
|
#endif
|
||||||
@ -360,6 +402,10 @@ static void usage(void)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
WinFspLoad();
|
||||||
|
#endif
|
||||||
|
|
||||||
PTFS ptfs = { 0 };
|
PTFS ptfs = { 0 };
|
||||||
|
|
||||||
if (3 <= argc && '-' != argv[argc - 2][0] && '-' != argv[argc - 1][0])
|
if (3 <= argc && '-' != argv[argc - 2][0] && '-' != argv[argc - 1][0])
|
||||||
@ -413,5 +459,17 @@ int main(int argc, char *argv[])
|
|||||||
if (0 == ptfs.rootdir)
|
if (0 == ptfs.rootdir)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
if (-1 != getpath(ptfs.rootdir, buf, sizeof buf))
|
||||||
|
{
|
||||||
|
ptfs.rootlen = strlen(buf);
|
||||||
|
if (1 == ptfs.rootlen)
|
||||||
|
ptfs.rootlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return fuse_main(argc, argv, &ptfs_ops, &ptfs);
|
return fuse_main(argc, argv, &ptfs_ops, &ptfs);
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,26 @@ int open(const char *path, int oflag, ...)
|
|||||||
return (int)(intptr_t)h;
|
return (int)(intptr_t)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fgetpath(int fd, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||||
|
WCHAR FileName[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
DWORD FileNameLength;
|
||||||
|
|
||||||
|
FileNameLength = GetFinalPathNameByHandleW(h, FileName, sizeof FileName / sizeof(WCHAR),
|
||||||
|
VOLUME_NAME_NONE | FILE_NAME_NORMALIZED);
|
||||||
|
if (0 == FileNameLength)
|
||||||
|
return error();
|
||||||
|
|
||||||
|
FspPosixEncodeWindowsPath(FileName, FileNameLength);
|
||||||
|
size = WideCharToMultiByte(CP_UTF8, 0, FileName, FileNameLength, buf, (int)(size - 1), 0, 0);
|
||||||
|
if (0 == size)
|
||||||
|
return error();
|
||||||
|
buf[size] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fstat(int fd, struct fuse_stat *stbuf)
|
int fstat(int fd, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||||
@ -303,6 +323,22 @@ int close(int fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getpath(const char *path, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
HANDLE h = CreateFileA(path,
|
||||||
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == h)
|
||||||
|
return error();
|
||||||
|
|
||||||
|
int res = fgetpath((int)(intptr_t)h, buf, size);
|
||||||
|
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf)
|
int lstat(const char *path, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
HANDLE h = CreateFileA(path,
|
||||||
|
@ -46,6 +46,7 @@ char *realpath(const char *path, char *resolved);
|
|||||||
int statvfs(const char *path, struct fuse_statvfs *stbuf);
|
int statvfs(const char *path, struct fuse_statvfs *stbuf);
|
||||||
|
|
||||||
int open(const char *path, int oflag, ...);
|
int open(const char *path, int oflag, ...);
|
||||||
|
int fgetpath(int fd, char *buf, size_t size);
|
||||||
int fstat(int fd, struct fuse_stat *stbuf);
|
int fstat(int fd, struct fuse_stat *stbuf);
|
||||||
int ftruncate(int fd, fuse_off_t size);
|
int ftruncate(int fd, fuse_off_t size);
|
||||||
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset);
|
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset);
|
||||||
@ -53,6 +54,7 @@ int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset);
|
|||||||
int fsync(int fd);
|
int fsync(int fd);
|
||||||
int close(int fd);
|
int close(int fd);
|
||||||
|
|
||||||
|
int getpath(const char *path, char *buf, size_t size);
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf);
|
int lstat(const char *path, struct fuse_stat *stbuf);
|
||||||
int chmod(const char *path, fuse_mode_t mode);
|
int chmod(const char *path, fuse_mode_t mode);
|
||||||
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid);
|
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid);
|
||||||
@ -79,8 +81,5 @@ struct dirent *readdir(DIR *dirp);
|
|||||||
int closedir(DIR *dirp);
|
int closedir(DIR *dirp);
|
||||||
|
|
||||||
long WinFspLoad(void);
|
long WinFspLoad(void);
|
||||||
#undef fuse_main
|
|
||||||
#define fuse_main(argc, argv, ops, data)\
|
|
||||||
(WinFspLoad(), fuse_main_real(argc, argv, ops, sizeof *(ops), data))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <winfsp/winfsp.h>
|
#include <winfsp/winfsp.h>
|
||||||
#include <tlib/testsuite.h>
|
#include <tlib/testsuite.h>
|
||||||
|
#include <strsafe.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
@ -145,7 +146,7 @@ static void dirbuf_dots_test(void)
|
|||||||
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dirbuf_fill_dotest(unsigned seed, ULONG Count, ULONG InvalidCount)
|
static void dirbuf_fill_dotest(unsigned seed, ULONG Count, ULONG InvalidCount, BOOLEAN Presort)
|
||||||
{
|
{
|
||||||
PVOID DirBuffer = 0;
|
PVOID DirBuffer = 0;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -162,6 +163,7 @@ static void dirbuf_fill_dotest(unsigned seed, ULONG Count, ULONG InvalidCount)
|
|||||||
ULONG DotIndex = Count / 3, DotDotIndex = Count / 3 * 2;
|
ULONG DotIndex = Count / 3, DotDotIndex = Count / 3 * 2;
|
||||||
WCHAR Marker[MAX_PATH];
|
WCHAR Marker[MAX_PATH];
|
||||||
ULONG N, MarkerIndex, MarkerLength;
|
ULONG N, MarkerIndex, MarkerLength;
|
||||||
|
UINT64 PresortIndex = 0;
|
||||||
|
|
||||||
srand(seed);
|
srand(seed);
|
||||||
|
|
||||||
@ -189,12 +191,18 @@ static void dirbuf_fill_dotest(unsigned seed, ULONG Count, ULONG InvalidCount)
|
|||||||
DirInfo->FileNameBuf[0] = L'.';
|
DirInfo->FileNameBuf[0] = L'.';
|
||||||
DirInfo->FileNameBuf[1] = L'.';
|
DirInfo->FileNameBuf[1] = L'.';
|
||||||
}
|
}
|
||||||
else
|
else if (!Presort)
|
||||||
{
|
{
|
||||||
N = 24 + rand() % (32 - 24);
|
N = 24 + rand() % (32 - 24);
|
||||||
for (ULONG J = 0; N > J; J++)
|
for (ULONG J = 0; N > J; J++)
|
||||||
DirInfo->FileNameBuf[J] = 'A' + rand() % 26;
|
DirInfo->FileNameBuf[J] = 'A' + rand() % 26;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
N = 24;
|
||||||
|
StringCbPrintfW(DirInfo->FileNameBuf, 64, L"FILEFILE%016llx", PresortIndex);
|
||||||
|
PresortIndex++;
|
||||||
|
}
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + N * sizeof(WCHAR));
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + N * sizeof(WCHAR));
|
||||||
|
|
||||||
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
||||||
@ -212,7 +220,7 @@ static void dirbuf_fill_dotest(unsigned seed, ULONG Count, ULONG InvalidCount)
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRWLOCK Lock;
|
SRWLOCK Lock;
|
||||||
ULONG Capacity, LoMark, HiMark;
|
ULONG InitialCapacity, Capacity, LoMark, HiMark;
|
||||||
PUINT8 Buffer;
|
PUINT8 Buffer;
|
||||||
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
|
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
|
||||||
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *PeekDirBuffer = DirBuffer;
|
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *PeekDirBuffer = DirBuffer;
|
||||||
@ -348,31 +356,60 @@ static void dirbuf_fill_test(void)
|
|||||||
{
|
{
|
||||||
unsigned seed = (unsigned)time(0);
|
unsigned seed = (unsigned)time(0);
|
||||||
|
|
||||||
dirbuf_fill_dotest(1485473509, 10, 0);
|
dirbuf_fill_dotest(1485473509, 10, 0, FALSE);
|
||||||
dirbuf_fill_dotest(1485473509, 10, 3);
|
dirbuf_fill_dotest(1485473509, 10, 3, FALSE);
|
||||||
|
|
||||||
for (ULONG I = 0; 10000 > I; I++)
|
for (ULONG I = 0; 10000 > I; I++)
|
||||||
{
|
{
|
||||||
dirbuf_fill_dotest(seed + I, 10, 0);
|
dirbuf_fill_dotest(seed + I, 10, 0, FALSE);
|
||||||
dirbuf_fill_dotest(seed + I, 10, 3);
|
dirbuf_fill_dotest(seed + I, 10, 3, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ULONG I = 0; 1000 > I; I++)
|
for (ULONG I = 0; 1000 > I; I++)
|
||||||
{
|
{
|
||||||
dirbuf_fill_dotest(seed + I, 100, 0);
|
dirbuf_fill_dotest(seed + I, 100, 0, FALSE);
|
||||||
dirbuf_fill_dotest(seed + I, 100, 30);
|
dirbuf_fill_dotest(seed + I, 100, 30, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ULONG I = 0; 100 > I; I++)
|
for (ULONG I = 0; 100 > I; I++)
|
||||||
{
|
{
|
||||||
dirbuf_fill_dotest(seed + I, 1000, 0);
|
dirbuf_fill_dotest(seed + I, 1000, 0, FALSE);
|
||||||
dirbuf_fill_dotest(seed + I, 1000, 300);
|
dirbuf_fill_dotest(seed + I, 1000, 300, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ULONG I = 0; 10 > I; I++)
|
for (ULONG I = 0; 10 > I; I++)
|
||||||
{
|
{
|
||||||
dirbuf_fill_dotest(seed + I, 10000, 0);
|
dirbuf_fill_dotest(seed + I, 10000, 0, FALSE);
|
||||||
dirbuf_fill_dotest(seed + I, 10000, 3000);
|
dirbuf_fill_dotest(seed + I, 10000, 3000, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dirbuf_presort_fill_test(void)
|
||||||
|
{
|
||||||
|
unsigned seed = (unsigned)time(0);
|
||||||
|
|
||||||
|
for (ULONG I = 0; 10000 > I; I++)
|
||||||
|
{
|
||||||
|
dirbuf_fill_dotest(seed + I, 10, 0, TRUE);
|
||||||
|
dirbuf_fill_dotest(seed + I, 10, 3, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ULONG I = 0; 1000 > I; I++)
|
||||||
|
{
|
||||||
|
dirbuf_fill_dotest(seed + I, 100, 0, TRUE);
|
||||||
|
dirbuf_fill_dotest(seed + I, 100, 30, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ULONG I = 0; 100 > I; I++)
|
||||||
|
{
|
||||||
|
dirbuf_fill_dotest(seed + I, 1000, 0, TRUE);
|
||||||
|
dirbuf_fill_dotest(seed + I, 1000, 300, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ULONG I = 0; 10 > I; I++)
|
||||||
|
{
|
||||||
|
dirbuf_fill_dotest(seed + I, 10000, 0, FALSE);
|
||||||
|
dirbuf_fill_dotest(seed + I, 10000, 3000, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,5 +509,6 @@ void dirbuf_tests(void)
|
|||||||
TEST(dirbuf_empty_test);
|
TEST(dirbuf_empty_test);
|
||||||
TEST(dirbuf_dots_test);
|
TEST(dirbuf_dots_test);
|
||||||
TEST(dirbuf_fill_test);
|
TEST(dirbuf_fill_test);
|
||||||
|
TEST(dirbuf_presort_fill_test);
|
||||||
TEST(dirbuf_boundary_test);
|
TEST(dirbuf_boundary_test);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, UL
|
|||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 1; 100 >= j; j++)
|
for (int j = 1; 400 >= j; j++)
|
||||||
{
|
{
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\fileABCDEFGHIJKLMNOPQRSTUVXWYZfile%d",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\fileABCDEFGHIJKLMNOPQRSTUVXWYZfile%d",
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), j);
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), j);
|
||||||
@ -90,7 +90,7 @@ static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, UL
|
|||||||
} while (FindNextFileW(Handle, &FindData));
|
} while (FindNextFileW(Handle, &FindData));
|
||||||
ASSERT(ERROR_NO_MORE_FILES == GetLastError());
|
ASSERT(ERROR_NO_MORE_FILES == GetLastError());
|
||||||
|
|
||||||
ASSERT(110 == FileCount);
|
ASSERT(410 == FileCount);
|
||||||
|
|
||||||
Success = FindClose(Handle);
|
Success = FindClose(Handle);
|
||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
@ -194,8 +194,8 @@ static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, UL
|
|||||||
} while (FindNextFileW(Handle, &FindData));
|
} while (FindNextFileW(Handle, &FindData));
|
||||||
ASSERT(ERROR_NO_MORE_FILES == GetLastError());
|
ASSERT(ERROR_NO_MORE_FILES == GetLastError());
|
||||||
|
|
||||||
ASSERT(100 == FileCount);
|
ASSERT(400 == FileCount);
|
||||||
ASSERT(101 * 100 / 2 == FileTotal);
|
ASSERT(401 * 400 / 2 == FileTotal);
|
||||||
|
|
||||||
Success = FindClose(Handle);
|
Success = FindClose(Handle);
|
||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
@ -224,7 +224,7 @@ static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, UL
|
|||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 1; 100 >= j; j++)
|
for (int j = 1; 400 >= j; j++)
|
||||||
{
|
{
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\fileABCDEFGHIJKLMNOPQRSTUVXWYZfile%d",
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\fileABCDEFGHIJKLMNOPQRSTUVXWYZfile%d",
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), j);
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), j);
|
||||||
|
Reference in New Issue
Block a user