├── .github
└── workflows
│ └── build.yml
├── .gitmodules
├── CMakeLists.txt
├── CMakeSettings.json
├── LICENCE
├── README.md
├── btrfs-dump.pl
├── mingw-amd64.cmake
├── mingw-x86.cmake
├── msvc-aarch64.cmake
├── msvc-amd64.cmake
├── msvc-armv7.cmake
├── msvc-x86.cmake
├── send-dump.pl
└── src
├── balance.c
├── blake2-impl.h
├── blake2b-ref.c
├── boot.c
├── btrfs-vol.inf
├── btrfs.c
├── btrfs.cdf
├── btrfs.h
├── btrfs.inf
├── btrfs.rc.in
├── btrfs_drv.h
├── btrfsioctl.h
├── cache.c
├── calcthread.c
├── compress.c
├── crc32c-aarch64.asm
├── crc32c-gas.S
├── crc32c-masm.asm
├── crc32c.c
├── crc32c.h
├── create.c
├── devctrl.c
├── dirctrl.c
├── extent-tree.c
├── fastio.c
├── fileinfo.c
├── flushthread.c
├── free-space.c
├── fsctl.c
├── fsrtl.c
├── galois.c
├── mkbtrfs
├── mkbtrfs.c
├── mkbtrfs.rc.in
└── resource.h
├── pnp.c
├── read.c
├── registry.c
├── reparse.c
├── resource.h
├── scrub.c
├── search.c
├── security.c
├── send.c
├── sha256.c
├── shellext
├── balance.cpp
├── balance.h
├── contextmenu.cpp
├── contextmenu.h
├── devices.cpp
├── devices.h
├── factory.cpp
├── factory.h
├── iconoverlay.cpp
├── iconoverlay.h
├── main.cpp
├── mappings.cpp
├── mountmgr.cpp
├── mountmgr.h
├── propsheet.cpp
├── propsheet.h
├── recv.cpp
├── recv.h
├── resource.h
├── scrub.cpp
├── scrub.h
├── send.cpp
├── send.h
├── shellbtrfs.def
├── shellbtrfs.manifest
├── shellbtrfs.rc.in
├── shellext.h
├── subvol.ico
├── subvol.svg
├── volpropsheet.cpp
└── volpropsheet.h
├── tests
├── create.cpp
├── cs.cpp
├── delete.cpp
├── ea.cpp
├── fileinfo.cpp
├── io.cpp
├── links.cpp
├── manifest.xml
├── mmap.cpp
├── oplock.cpp
├── overwrite.cpp
├── rename.cpp
├── reparse.cpp
├── security.cpp
├── streams.cpp
├── supersede.cpp
├── test.cpp
├── test.h
└── test.rc.in
├── treefuncs.c
├── ubtrfs
├── resource.h
├── ubtrfs.c
├── ubtrfs.def
└── ubtrfs.rc.in
├── volume.c
├── worker-thread.c
├── write.c
├── xor-gas.S
├── xor-masm.asm
└── zstd-shim.h
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 | on: [push]
3 | env:
4 | PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/eselect/wine/bin
5 | jobs:
6 | cmake:
7 | runs-on: msvc-wine
8 | container:
9 | volumes:
10 | - /var/run/pcscd/pcscd.comm:/var/run/pcscd/pcscd.comm
11 | steps:
12 | - run: echo "SHORT_SHA=`echo ${{ github.sha }} | cut -c1-8`" >> $GITHUB_ENV
13 | - run: git clone --recurse-submodules -j`nproc` ${{ github.server_url }}/${{ github.repository }} ${SHORT_SHA}
14 | - run: cd ${SHORT_SHA} && git checkout ${{ github.sha }}
15 | - run: mkdir -p build/debug/{amd64,x86,aarch64,arm}
16 | - run: mkdir -p build/release/{amd64,x86,aarch64,arm}
17 | - run: mkdir -p build/pdb/{debug,release}/{amd64,x86,aarch64,arm}
18 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-amd64.cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/debug/amd64 && cmake --build build/debug/amd64 --parallel `nproc`
19 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-x86.cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/debug/x86 && cmake --build build/debug/x86 --parallel `nproc`
20 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-aarch64.cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/debug/aarch64 && cmake --build build/debug/aarch64 --parallel `nproc`
21 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-armv7.cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/debug/arm && cmake --build build/debug/arm --parallel `nproc`
22 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-amd64.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/release/amd64 && cmake --build build/release/amd64 --parallel `nproc`
23 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-x86.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/release/x86 && cmake --build build/release/x86 --parallel `nproc`
24 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-aarch64.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/release/aarch64 && cmake --build build/release/aarch64 --parallel `nproc`
25 | - run: cmake -DCMAKE_TOOLCHAIN_FILE=msvc-armv7.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_TEST=OFF -S ${SHORT_SHA} -B build/release/arm && cmake --build build/release/arm --parallel `nproc`
26 | - run: mv build/debug/amd64/*.pdb build/pdb/debug/amd64/
27 | - run: mv build/debug/x86/*.pdb build/pdb/debug/x86/
28 | - run: mv build/debug/aarch64/*.pdb build/pdb/debug/aarch64/
29 | - run: mv build/debug/arm/*.pdb build/pdb/debug/arm/
30 | - run: mv build/release/amd64/*.pdb build/pdb/release/amd64/
31 | - run: mv build/release/x86/*.pdb build/pdb/release/x86/
32 | - run: mv build/release/aarch64/*.pdb build/pdb/release/aarch64/
33 | - run: mv build/release/arm/*.pdb build/pdb/release/arm/
34 | - run: cp ${SHORT_SHA}/src/{btrfs,btrfs-vol}.inf build/debug/
35 | - run: cp ${SHORT_SHA}/src/{btrfs,btrfs-vol}.inf build/release/
36 | - run: stampinf -f build/debug/btrfs.inf -d \* -v \*
37 | - run: stampinf -f build/debug/btrfs-vol.inf -d \* -v \*
38 | - run: stampinf -f build/release/btrfs.inf -d \* -v \*
39 | - run: stampinf -f build/release/btrfs-vol.inf -d \* -v \*
40 | - run: cd build/debug && makecat ../../${SHORT_SHA}/src/btrfs.cdf
41 | - run: cd build/release && makecat ../../${SHORT_SHA}/src/btrfs.cdf
42 | - env:
43 | CERTIFICATE: ${{ secrets.CERTIFICATE }}
44 | run: echo "${CERTIFICATE}" > codesigning.crt
45 | - env:
46 | PKCS11CERT: ${{ secrets.PKCS11CERT }}
47 | PKCS11KEY: ${{ secrets.PKCS11KEY }}
48 | run: for i in build/{debug,release}/btrfs.cat; do osslsigncode sign -pkcs11module /usr/lib64/libcrypto3PKCS.so -pkcs11cert "${PKCS11CERT}" -key "${PKCS11KEY}" -certs codesigning.crt -t http://timestamp.digicert.com -in $i -out tmp && mv tmp $i; done
49 | - env:
50 | PKCS11CERT: ${{ secrets.PKCS11CERT }}
51 | PKCS11KEY: ${{ secrets.PKCS11KEY }}
52 | run: for i in build/{debug,release}/{amd64,x86,aarch64,arm}/{btrfs.sys,mkbtrfs.exe,shellbtrfs.dll,ubtrfs.dll}; do osslsigncode sign -pkcs11module /usr/lib64/libcrypto3PKCS.so -pkcs11cert "${PKCS11CERT}" -key "${PKCS11KEY}" -certs codesigning.crt -t http://timestamp.digicert.com -ph -in $i -out tmp && mv tmp $i; done
53 | - uses: actions/upload-artifact@v3
54 | with:
55 | name: ${{ github.sha }}
56 | overwrite: true
57 | path: |
58 | build/**/btrfs.sys
59 | build/**/mkbtrfs.exe
60 | build/**/shellbtrfs.dll
61 | build/**/ubtrfs.dll
62 | build/**/*.inf
63 | build/**/*.cat
64 | build/pdb
65 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/zstd"]
2 | path = src/zstd
3 | url = https://github.com/facebook/zstd
4 | [submodule "src/zlib"]
5 | path = src/zlib
6 | url = https://github.com/madler/zlib
7 |
--------------------------------------------------------------------------------
/CMakeSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "x64-Debug",
5 | "generator": "Ninja",
6 | "configurationType": "Debug",
7 | "buildRoot": "${projectDir}\\out\\build\\${name}",
8 | "installRoot": "${projectDir}\\out\\install\\${name}",
9 | "cmakeCommandArgs": "",
10 | "buildCommandArgs": "-v",
11 | "ctestCommandArgs": "",
12 | "inheritEnvironments": [ "msvc_x64_x64" ],
13 | "variables": []
14 | },
15 | {
16 | "name": "x86-Debug",
17 | "generator": "Ninja",
18 | "configurationType": "Debug",
19 | "buildRoot": "${projectDir}\\out\\build\\${name}",
20 | "installRoot": "${projectDir}\\out\\install\\${name}",
21 | "cmakeCommandArgs": "",
22 | "buildCommandArgs": "-v",
23 | "ctestCommandArgs": "",
24 | "inheritEnvironments": [ "msvc_x86_x64" ],
25 | "variables": []
26 | },
27 | {
28 | "name": "arm-Debug",
29 | "generator": "Ninja",
30 | "configurationType": "Debug",
31 | "buildRoot": "${projectDir}\\out\\build\\${name}",
32 | "installRoot": "${projectDir}\\out\\install\\${name}",
33 | "cmakeCommandArgs": "",
34 | "buildCommandArgs": "-v",
35 | "ctestCommandArgs": "",
36 | "inheritEnvironments": [ "msvc_arm_x64" ],
37 | "variables": []
38 | },
39 | {
40 | "name": "arm64-Debug",
41 | "generator": "Ninja",
42 | "configurationType": "Debug",
43 | "buildRoot": "${projectDir}\\out\\build\\${name}",
44 | "installRoot": "${projectDir}\\out\\install\\${name}",
45 | "cmakeCommandArgs": "",
46 | "buildCommandArgs": "-v",
47 | "ctestCommandArgs": "",
48 | "inheritEnvironments": [ "msvc_arm64_x64" ],
49 | "variables": []
50 | },
51 | {
52 | "name": "x64-Release",
53 | "generator": "Ninja",
54 | "configurationType": "RelWithDebInfo",
55 | "buildRoot": "${projectDir}\\out\\build\\${name}",
56 | "installRoot": "${projectDir}\\out\\install\\${name}",
57 | "cmakeCommandArgs": "",
58 | "buildCommandArgs": "-v",
59 | "ctestCommandArgs": "",
60 | "inheritEnvironments": [ "msvc_x64_x64" ],
61 | "variables": []
62 | },
63 | {
64 | "name": "x86-Release",
65 | "generator": "Ninja",
66 | "configurationType": "RelWithDebInfo",
67 | "buildRoot": "${projectDir}\\out\\build\\${name}",
68 | "installRoot": "${projectDir}\\out\\install\\${name}",
69 | "cmakeCommandArgs": "",
70 | "buildCommandArgs": "-v",
71 | "ctestCommandArgs": "",
72 | "inheritEnvironments": [ "msvc_x86_x64" ],
73 | "variables": []
74 | },
75 | {
76 | "name": "arm-Release",
77 | "generator": "Ninja",
78 | "configurationType": "RelWithDebInfo",
79 | "buildRoot": "${projectDir}\\out\\build\\${name}",
80 | "installRoot": "${projectDir}\\out\\install\\${name}",
81 | "cmakeCommandArgs": "",
82 | "buildCommandArgs": "-v",
83 | "ctestCommandArgs": "",
84 | "inheritEnvironments": [ "msvc_arm_x64" ],
85 | "variables": []
86 | },
87 | {
88 | "name": "arm64-Release",
89 | "generator": "Ninja",
90 | "configurationType": "RelWithDebInfo",
91 | "buildRoot": "${projectDir}\\out\\build\\${name}",
92 | "installRoot": "${projectDir}\\out\\install\\${name}",
93 | "cmakeCommandArgs": "",
94 | "buildCommandArgs": "-v",
95 | "ctestCommandArgs": "",
96 | "inheritEnvironments": [ "msvc_arm64_x64" ],
97 | "variables": []
98 | }
99 | ]
100 | }
101 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/mingw-amd64.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # To Cross-compile, use:
3 | # cmake -DCMAKE_TOOLCHAIN_FILE=../mingw.cmake ..
4 | #
5 | # the name of the target operating system
6 | SET(CMAKE_SYSTEM_NAME Windows)
7 |
8 | # which compilers to use for C and C++
9 | SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
10 | SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
11 | SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
12 |
13 | # here is the target environment located
14 | SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
15 |
16 | # adjust the default behaviour of the FIND_XXX() commands:
17 | # search headers and libraries in the target environment, search
18 | # programs in the host environment
19 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
20 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
21 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
22 |
23 | set(CMAKE_PREFIX_PATH /usr/x86_64-w64-mingw32/usr/lib/cmake)
24 |
25 | set(CMAKE_SYSTEM_PROCESSOR x86_64)
26 |
--------------------------------------------------------------------------------
/mingw-x86.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # To Cross-compile, use:
3 | # cmake -DCMAKE_TOOLCHAIN_FILE=../mingw.cmake ..
4 | #
5 | # the name of the target operating system
6 | SET(CMAKE_SYSTEM_NAME Windows)
7 |
8 | # which compilers to use for C and C++
9 | SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
10 | SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
11 | SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
12 |
13 | SET(CMAKE_C_FLAGS "-m32")
14 | SET(CMAKE_CXX_FLAGS "-m32")
15 | SET(CMAKE_RC_FLAGS "-F pe-i386")
16 | SET(CMAKE_ASM_FLAGS "-m32")
17 |
18 | # here is the target environment located
19 | SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
20 |
21 | # adjust the default behaviour of the FIND_XXX() commands:
22 | # search headers and libraries in the target environment, search
23 | # programs in the host environment
24 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
27 |
28 | set(CMAKE_PREFIX_PATH /usr/i686-w64-mingw32/usr/lib/cmake)
29 |
30 | set(CMAKE_SYSTEM_PROCESSOR x86)
31 |
--------------------------------------------------------------------------------
/msvc-aarch64.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 |
3 | SET(CMAKE_C_COMPILER /opt/msvc/bin/arm64/cl)
4 | SET(CMAKE_CXX_COMPILER /opt/msvc/bin/arm64/cl)
5 | SET(CMAKE_RC_COMPILER /opt/msvc/bin/arm64/rc)
6 |
7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
8 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /MANIFEST:NO")
9 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO")
10 |
--------------------------------------------------------------------------------
/msvc-amd64.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 |
3 | SET(CMAKE_C_COMPILER /opt/msvc/bin/x64/cl)
4 | SET(CMAKE_CXX_COMPILER /opt/msvc/bin/x64/cl)
5 | SET(CMAKE_RC_COMPILER /opt/msvc/bin/x64/rc)
6 |
7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
8 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /MANIFEST:NO")
9 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO")
10 |
--------------------------------------------------------------------------------
/msvc-armv7.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 |
3 | SET(CMAKE_C_COMPILER /opt/msvc/bin/arm/cl)
4 | SET(CMAKE_CXX_COMPILER /opt/msvc/bin/arm/cl)
5 | SET(CMAKE_RC_COMPILER /opt/msvc/bin/arm/rc)
6 |
7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
8 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /MANIFEST:NO")
9 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO")
10 |
--------------------------------------------------------------------------------
/msvc-x86.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 |
3 | SET(CMAKE_C_COMPILER /opt/msvc/bin/x86/cl)
4 | SET(CMAKE_CXX_COMPILER /opt/msvc/bin/x86/cl)
5 | SET(CMAKE_RC_COMPILER /opt/msvc/bin/x86/rc)
6 |
7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
8 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /MANIFEST:NO")
9 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO")
10 |
11 | set(CMAKE_PREFIX_PATH "/home/hellas/wine/vcpkg/installed/x64-windows")
12 |
--------------------------------------------------------------------------------
/send-dump.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | # Dumper for btrfs send streams.
4 | # Released under the same terms, or lack thereof, as btrfs-dump.pl.
5 |
6 | open($f,$ARGV[0]) or die "Error opening ".$ARGV[0].": ".$!;
7 | binmode($f);
8 |
9 | while (!eof($f)) {
10 | do_stream($f);
11 |
12 | if (!eof($f)) {
13 | print "---\n";
14 | }
15 | }
16 |
17 | close($f);
18 |
19 | sub do_stream {
20 | my ($f)=@_;
21 |
22 | read($f,$a,0x11);
23 | ($magic,$ver)=unpack("a13V",$a);
24 |
25 | if ($magic ne "btrfs-stream\0") {
26 | printf STDERR "Not a send file.\n";
27 | close($f);
28 | exit;
29 | }
30 |
31 | if ($ver != 1 && $ver != 2) {
32 | printf STDERR "Version $ver not supported.\n";
33 | close($f);
34 | exit;
35 | }
36 |
37 | $type = 0;
38 | while (!eof($f) && $type != 21) {
39 | read($f,$a,0xa);
40 | ($len,$type,$crc)=unpack("VvV",$a);
41 |
42 | if ($type == 1) {
43 | printf("subvol, %x, %08x\n", $len, $crc);
44 | } elsif ($type == 2) {
45 | printf("snapshot, %x, %08x\n", $len, $crc);
46 | } elsif ($type == 3) {
47 | printf("mkfile, %x, %08x\n", $len, $crc);
48 | } elsif ($type == 4) {
49 | printf("mkdir, %x, %08x\n", $len, $crc);
50 | } elsif ($type == 5) {
51 | printf("mknod, %x, %08x\n", $len, $crc);
52 | } elsif ($type == 6) {
53 | printf("mkfifo, %x, %08x\n", $len, $crc);
54 | } elsif ($type == 7) {
55 | printf("mksock, %x, %08x\n", $len, $crc);
56 | } elsif ($type == 8) {
57 | printf("symlink, %x, %08x\n", $len, $crc);
58 | } elsif ($type == 9) {
59 | printf("rename, %x, %08x\n", $len, $crc);
60 | } elsif ($type == 10) {
61 | printf("link, %x, %08x\n", $len, $crc);
62 | } elsif ($type == 11) {
63 | printf("unlink, %x, %08x\n", $len, $crc);
64 | } elsif ($type == 12) {
65 | printf("rmdir, %x, %08x\n", $len, $crc);
66 | } elsif ($type == 13) {
67 | printf("set_xattr, %x, %08x\n", $len, $crc);
68 | } elsif ($type == 14) {
69 | printf("remove_xattr, %x, %08x\n", $len, $crc);
70 | } elsif ($type == 15) {
71 | printf("write, %x, %08x\n", $len, $crc);
72 | } elsif ($type == 16) {
73 | printf("clone, %x, %08x\n", $len, $crc);
74 | } elsif ($type == 17) {
75 | printf("truncate, %x, %08x\n", $len, $crc);
76 | } elsif ($type == 18) {
77 | printf("chmod, %x, %08x\n", $len, $crc);
78 | } elsif ($type == 19) {
79 | printf("chown, %x, %08x\n", $len, $crc);
80 | } elsif ($type == 20) {
81 | printf("utimes, %x, %08x\n", $len, $crc);
82 | } elsif ($type == 21) {
83 | printf("end, %x, %08x\n", $len, $crc);
84 | } elsif ($type == 22) {
85 | printf("update-extent, %x, %08x\n", $len, $crc);
86 | } elsif ($type == 23) {
87 | printf("fallocate, %x, %08x\n", $len, $crc);
88 | } elsif ($type == 24) {
89 | printf("fileattr, %x, %08x\n", $len, $crc);
90 | } elsif ($type == 25) {
91 | printf("encoded-write, %x, %08x\n", $len, $crc);
92 | } else {
93 | printf("unknown(%x), %x, %08x\n", $type, $len, $crc);
94 | }
95 |
96 | read($f,$b,$len);
97 | print_tlvs($b);
98 | }
99 | }
100 |
101 | sub btrfstime {
102 | my ($t)=@_;
103 |
104 | my $ut = unpack("Q",$t);
105 | my @lt = localtime($ut);
106 |
107 | return sprintf("%04u-%02u-%02u %02u:%02u:%02u",$lt[5]+1900,$lt[4]+1,$lt[3],$lt[2],$lt[1],$lt[0]);
108 | }
109 |
110 | sub print_tlvs {
111 | my ($b)=@_;
112 |
113 | while (length($b)>0) {
114 | my ($t,$l)=unpack("vv",$b);
115 |
116 | if ($t == 1) {
117 | printf(" uuid: %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", unpack("NnnnCCCCCC",substr($b,4,$l)));
118 | $b=substr($b,$l+4);
119 | } elsif ($t == 2) {
120 | printf(" transid: %x\n", unpack("Q",substr($b,4,$l)));
121 | $b=substr($b,$l+4);
122 | } elsif ($t == 3) {
123 | printf(" inode: %x\n", unpack("Q",substr($b,4,$l)));
124 | $b=substr($b,$l+4);
125 | } elsif ($t == 4) {
126 | printf(" size: %x\n", unpack("Q",substr($b,4,$l)));
127 | $b=substr($b,$l+4);
128 | } elsif ($t == 5) {
129 | printf(" mode: %o\n", unpack("Q",substr($b,4,$l)));
130 | $b=substr($b,$l+4);
131 | } elsif ($t == 6) {
132 | printf(" uid: %u\n", unpack("Q",substr($b,4,$l)));
133 | $b=substr($b,$l+4);
134 | } elsif ($t == 7) {
135 | printf(" gid: %u\n", unpack("Q",substr($b,4,$l)));
136 | $b=substr($b,$l+4);
137 | } elsif ($t == 8) {
138 | printf(" rdev: %x\n", unpack("Q",substr($b,4,$l)));
139 | $b=substr($b,$l+4);
140 | } elsif ($t == 9) {
141 | printf(" ctime: %s\n", btrfstime(substr($b,4,$l)));
142 | $b=substr($b,$l+4);
143 | } elsif ($t == 10) {
144 | printf(" mtime: %s\n", btrfstime(substr($b,4,$l)));
145 | $b=substr($b,$l+4);
146 | } elsif ($t == 11) {
147 | printf(" atime: %s\n", btrfstime(substr($b,4,$l)));
148 | $b=substr($b,$l+4);
149 | } elsif ($t == 12) {
150 | printf(" otime: %s\n", btrfstime(substr($b,4,$l)));
151 | $b=substr($b,$l+4);
152 | } elsif ($t == 13) {
153 | printf(" xattr_name: \"%s\"\n", substr($b,4,$l));
154 | $b=substr($b,$l+4);
155 | } elsif ($t == 14) {
156 | printf(" xattr_data: \"%s\"\n", substr($b,4,$l));
157 | $b=substr($b,$l+4);
158 | } elsif ($t == 15) {
159 | printf(" path: \"%s\"\n", substr($b,4,$l));
160 | $b=substr($b,$l+4);
161 | } elsif ($t == 16) {
162 | printf(" path_to: \"%s\"\n", substr($b,4,$l));
163 | $b=substr($b,$l+4);
164 | } elsif ($t == 17) {
165 | printf(" path_link: \"%s\"\n", substr($b,4,$l));
166 | $b=substr($b,$l+4);
167 | } elsif ($t == 18) {
168 | printf(" offset: %x\n", unpack("Q",substr($b,4,$l)));
169 | $b=substr($b,$l+4);
170 | } elsif ($t == 19) {
171 | if ($ver == 2) {
172 | printf(" data: (%x bytes)\n", length($b) - 2); # FIXME
173 | $b="";
174 | } else {
175 | printf(" data: (%x bytes)\n", $l);
176 | $b=substr($b,$l+4);
177 | }
178 | } elsif ($t == 20) {
179 | printf(" clone_uuid: %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", unpack("NnnnCCCCCC",substr($b,4,$l)));
180 | $b=substr($b,$l+4);
181 | } elsif ($t == 21) {
182 | printf(" clone_transid: %x\n", unpack("Q",substr($b,4,$l)));
183 | $b=substr($b,$l+4);
184 | } elsif ($t == 22) {
185 | printf(" clone_path: \"%s\"\n", substr($b,4,$l));
186 | $b=substr($b,$l+4);
187 | } elsif ($t == 23) {
188 | printf(" clone_offset: %x\n", unpack("Q",substr($b,4,$l)));
189 | $b=substr($b,$l+4);
190 | } elsif ($t == 24) {
191 | printf(" clone_len: %x\n", unpack("Q",substr($b,4,$l)));
192 | $b=substr($b,$l+4);
193 | } elsif ($t == 25) {
194 | printf(" fallocate_mode: %x\n", unpack("V",substr($b,4,$l)));
195 | $b=substr($b,$l+4);
196 | } elsif ($t == 26) {
197 | printf(" fileattr: %x\n", unpack("Q",substr($b,4,$l)));
198 | $b=substr($b,$l+4);
199 | } elsif ($t == 27) {
200 | printf(" unencoded_file_len: %x\n", unpack("Q",substr($b,4,$l)));
201 | $b=substr($b,$l+4);
202 | } elsif ($t == 28) {
203 | printf(" unencoded_len: %x\n", unpack("Q",substr($b,4,$l)));
204 | $b=substr($b,$l+4);
205 | } elsif ($t == 29) {
206 | printf(" unencoded_offset: %x\n", unpack("Q",substr($b,4,$l)));
207 | $b=substr($b,$l+4);
208 | } elsif ($t == 30) {
209 | printf(" compression: %x\n", unpack("V",substr($b,4,$l)));
210 | $b=substr($b,$l+4);
211 | } elsif ($t == 31) {
212 | printf(" encryption: %x\n", unpack("V",substr($b,4,$l)));
213 | $b=substr($b,$l+4);
214 | } else {
215 | printf(" unknown(%u),%x\n",$t,$l);
216 | $b=substr($b,$l+4);
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/blake2-impl.h:
--------------------------------------------------------------------------------
1 | /*
2 | BLAKE2 reference source code package - reference C implementations
3 |
4 | Copyright 2012, Samuel Neves . You may use this under the
5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6 | your option. The terms of these licenses can be found at:
7 |
8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9 | - OpenSSL license : https://www.openssl.org/source/license.html
10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | More information about the BLAKE2 hash function can be found at
13 | https://blake2.net.
14 | */
15 | #pragma once
16 |
17 | #include
18 | #include
19 |
20 | #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
21 | #if defined(_MSC_VER)
22 | #define BLAKE2_INLINE __inline
23 | #elif defined(__GNUC__)
24 | #define BLAKE2_INLINE __inline__
25 | #else
26 | #define BLAKE2_INLINE
27 | #endif
28 | #else
29 | #define BLAKE2_INLINE inline
30 | #endif
31 |
32 | #define NATIVE_LITTLE_ENDIAN
33 |
34 | static BLAKE2_INLINE uint32_t load32( const void *src )
35 | {
36 | #if defined(NATIVE_LITTLE_ENDIAN)
37 | uint32_t w;
38 | memcpy(&w, src, sizeof w);
39 | return w;
40 | #else
41 | const uint8_t *p = ( const uint8_t * )src;
42 | return (( uint32_t )( p[0] ) << 0) |
43 | (( uint32_t )( p[1] ) << 8) |
44 | (( uint32_t )( p[2] ) << 16) |
45 | (( uint32_t )( p[3] ) << 24) ;
46 | #endif
47 | }
48 |
49 | static BLAKE2_INLINE uint64_t load64( const void *src )
50 | {
51 | #if defined(NATIVE_LITTLE_ENDIAN)
52 | uint64_t w;
53 | memcpy(&w, src, sizeof w);
54 | return w;
55 | #else
56 | const uint8_t *p = ( const uint8_t * )src;
57 | return (( uint64_t )( p[0] ) << 0) |
58 | (( uint64_t )( p[1] ) << 8) |
59 | (( uint64_t )( p[2] ) << 16) |
60 | (( uint64_t )( p[3] ) << 24) |
61 | (( uint64_t )( p[4] ) << 32) |
62 | (( uint64_t )( p[5] ) << 40) |
63 | (( uint64_t )( p[6] ) << 48) |
64 | (( uint64_t )( p[7] ) << 56) ;
65 | #endif
66 | }
67 |
68 | static BLAKE2_INLINE uint16_t load16( const void *src )
69 | {
70 | #if defined(NATIVE_LITTLE_ENDIAN)
71 | uint16_t w;
72 | memcpy(&w, src, sizeof w);
73 | return w;
74 | #else
75 | const uint8_t *p = ( const uint8_t * )src;
76 | return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
77 | (( uint32_t )( p[1] ) << 8));
78 | #endif
79 | }
80 |
81 | static BLAKE2_INLINE void store16( void *dst, uint16_t w )
82 | {
83 | #if defined(NATIVE_LITTLE_ENDIAN)
84 | memcpy(dst, &w, sizeof w);
85 | #else
86 | uint8_t *p = ( uint8_t * )dst;
87 | *p++ = ( uint8_t )w; w >>= 8;
88 | *p++ = ( uint8_t )w;
89 | #endif
90 | }
91 |
92 | static BLAKE2_INLINE void store32( void *dst, uint32_t w )
93 | {
94 | #if defined(NATIVE_LITTLE_ENDIAN)
95 | memcpy(dst, &w, sizeof w);
96 | #else
97 | uint8_t *p = ( uint8_t * )dst;
98 | p[0] = (uint8_t)(w >> 0);
99 | p[1] = (uint8_t)(w >> 8);
100 | p[2] = (uint8_t)(w >> 16);
101 | p[3] = (uint8_t)(w >> 24);
102 | #endif
103 | }
104 |
105 | static BLAKE2_INLINE void store64( void *dst, uint64_t w )
106 | {
107 | #if defined(NATIVE_LITTLE_ENDIAN)
108 | memcpy(dst, &w, sizeof w);
109 | #else
110 | uint8_t *p = ( uint8_t * )dst;
111 | p[0] = (uint8_t)(w >> 0);
112 | p[1] = (uint8_t)(w >> 8);
113 | p[2] = (uint8_t)(w >> 16);
114 | p[3] = (uint8_t)(w >> 24);
115 | p[4] = (uint8_t)(w >> 32);
116 | p[5] = (uint8_t)(w >> 40);
117 | p[6] = (uint8_t)(w >> 48);
118 | p[7] = (uint8_t)(w >> 56);
119 | #endif
120 | }
121 |
122 | static BLAKE2_INLINE uint64_t load48( const void *src )
123 | {
124 | const uint8_t *p = ( const uint8_t * )src;
125 | return (( uint64_t )( p[0] ) << 0) |
126 | (( uint64_t )( p[1] ) << 8) |
127 | (( uint64_t )( p[2] ) << 16) |
128 | (( uint64_t )( p[3] ) << 24) |
129 | (( uint64_t )( p[4] ) << 32) |
130 | (( uint64_t )( p[5] ) << 40) ;
131 | }
132 |
133 | static BLAKE2_INLINE void store48( void *dst, uint64_t w )
134 | {
135 | uint8_t *p = ( uint8_t * )dst;
136 | p[0] = (uint8_t)(w >> 0);
137 | p[1] = (uint8_t)(w >> 8);
138 | p[2] = (uint8_t)(w >> 16);
139 | p[3] = (uint8_t)(w >> 24);
140 | p[4] = (uint8_t)(w >> 32);
141 | p[5] = (uint8_t)(w >> 40);
142 | }
143 |
144 | static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
145 | {
146 | return ( w >> c ) | ( w << ( 32 - c ) );
147 | }
148 |
149 | static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
150 | {
151 | return ( w >> c ) | ( w << ( 64 - c ) );
152 | }
153 |
154 | #if defined(_MSC_VER)
155 | #define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
156 | #else
157 | #define BLAKE2_PACKED(x) x __attribute__((packed))
158 | #endif
159 |
160 | enum blake2b_constant
161 | {
162 | BLAKE2B_BLOCKBYTES = 128,
163 | BLAKE2B_OUTBYTES = 64,
164 | BLAKE2B_KEYBYTES = 64,
165 | BLAKE2B_SALTBYTES = 16,
166 | BLAKE2B_PERSONALBYTES = 16
167 | };
168 |
169 | typedef struct blake2b_state__
170 | {
171 | uint64_t h[8];
172 | uint64_t t[2];
173 | uint64_t f[2];
174 | uint8_t buf[BLAKE2B_BLOCKBYTES];
175 | size_t buflen;
176 | size_t outlen;
177 | uint8_t last_node;
178 | } blake2b_state;
179 |
180 | BLAKE2_PACKED(struct blake2b_param__
181 | {
182 | uint8_t digest_length; /* 1 */
183 | uint8_t key_length; /* 2 */
184 | uint8_t fanout; /* 3 */
185 | uint8_t depth; /* 4 */
186 | uint32_t leaf_length; /* 8 */
187 | uint32_t node_offset; /* 12 */
188 | uint32_t xof_length; /* 16 */
189 | uint8_t node_depth; /* 17 */
190 | uint8_t inner_length; /* 18 */
191 | uint8_t reserved[14]; /* 32 */
192 | uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
193 | uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
194 | });
195 |
196 | typedef struct blake2b_param__ blake2b_param;
197 |
--------------------------------------------------------------------------------
/src/blake2b-ref.c:
--------------------------------------------------------------------------------
1 | /*
2 | BLAKE2 reference source code package - reference C implementations
3 |
4 | Copyright 2012, Samuel Neves . You may use this under the
5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6 | your option. The terms of these licenses can be found at:
7 |
8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9 | - OpenSSL license : https://www.openssl.org/source/license.html
10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | More information about the BLAKE2 hash function can be found at
13 | https://blake2.net.
14 | */
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #include "blake2-impl.h"
21 |
22 | static const uint64_t blake2b_IV[8] =
23 | {
24 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
25 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
26 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
27 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
28 | };
29 |
30 | static const uint8_t blake2b_sigma[12][16] =
31 | {
32 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
33 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
34 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
35 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
36 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
37 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
38 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
39 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
40 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
41 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
42 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
43 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
44 | };
45 |
46 | static int blake2b_update(blake2b_state* S, const void* in, size_t inlen);
47 |
48 | static void blake2b_set_lastnode( blake2b_state *S )
49 | {
50 | S->f[1] = (uint64_t)-1;
51 | }
52 |
53 | /* Some helper functions, not necessarily useful */
54 | static int blake2b_is_lastblock( const blake2b_state *S )
55 | {
56 | return S->f[0] != 0;
57 | }
58 |
59 | static void blake2b_set_lastblock( blake2b_state *S )
60 | {
61 | if( S->last_node ) blake2b_set_lastnode( S );
62 |
63 | S->f[0] = (uint64_t)-1;
64 | }
65 |
66 | static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
67 | {
68 | S->t[0] += inc;
69 | S->t[1] += ( S->t[0] < inc );
70 | }
71 |
72 | static void blake2b_init0( blake2b_state *S )
73 | {
74 | size_t i;
75 | memset( S, 0, sizeof( blake2b_state ) );
76 |
77 | for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
78 | }
79 |
80 | /* init xors IV with input parameter block */
81 | static void blake2b_init_param( blake2b_state *S, const blake2b_param *P )
82 | {
83 | const uint8_t *p = ( const uint8_t * )( P );
84 | size_t i;
85 |
86 | blake2b_init0( S );
87 |
88 | /* IV XOR ParamBlock */
89 | for( i = 0; i < 8; ++i )
90 | S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
91 |
92 | S->outlen = P->digest_length;
93 | }
94 |
95 |
96 |
97 | static void blake2b_init( blake2b_state *S, size_t outlen )
98 | {
99 | blake2b_param P[1];
100 |
101 | P->digest_length = (uint8_t)outlen;
102 | P->key_length = 0;
103 | P->fanout = 1;
104 | P->depth = 1;
105 | store32( &P->leaf_length, 0 );
106 | store32( &P->node_offset, 0 );
107 | store32( &P->xof_length, 0 );
108 | P->node_depth = 0;
109 | P->inner_length = 0;
110 | memset( P->reserved, 0, sizeof( P->reserved ) );
111 | memset( P->salt, 0, sizeof( P->salt ) );
112 | memset( P->personal, 0, sizeof( P->personal ) );
113 |
114 | blake2b_init_param( S, P );
115 | }
116 |
117 | #define G(r,i,a,b,c,d) \
118 | do { \
119 | a = a + b + m[blake2b_sigma[r][2*i+0]]; \
120 | d = rotr64(d ^ a, 32); \
121 | c = c + d; \
122 | b = rotr64(b ^ c, 24); \
123 | a = a + b + m[blake2b_sigma[r][2*i+1]]; \
124 | d = rotr64(d ^ a, 16); \
125 | c = c + d; \
126 | b = rotr64(b ^ c, 63); \
127 | } while(0)
128 |
129 | #define ROUND(r) \
130 | do { \
131 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
132 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
133 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \
134 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \
135 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \
136 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \
137 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
138 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
139 | } while(0)
140 |
141 | static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
142 | {
143 | uint64_t m[16];
144 | uint64_t v[16];
145 | size_t i;
146 |
147 | for( i = 0; i < 16; ++i ) {
148 | m[i] = load64( block + i * sizeof( m[i] ) );
149 | }
150 |
151 | for( i = 0; i < 8; ++i ) {
152 | v[i] = S->h[i];
153 | }
154 |
155 | v[ 8] = blake2b_IV[0];
156 | v[ 9] = blake2b_IV[1];
157 | v[10] = blake2b_IV[2];
158 | v[11] = blake2b_IV[3];
159 | v[12] = blake2b_IV[4] ^ S->t[0];
160 | v[13] = blake2b_IV[5] ^ S->t[1];
161 | v[14] = blake2b_IV[6] ^ S->f[0];
162 | v[15] = blake2b_IV[7] ^ S->f[1];
163 |
164 | ROUND( 0 );
165 | ROUND( 1 );
166 | ROUND( 2 );
167 | ROUND( 3 );
168 | ROUND( 4 );
169 | ROUND( 5 );
170 | ROUND( 6 );
171 | ROUND( 7 );
172 | ROUND( 8 );
173 | ROUND( 9 );
174 | ROUND( 10 );
175 | ROUND( 11 );
176 |
177 | for( i = 0; i < 8; ++i ) {
178 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
179 | }
180 | }
181 |
182 | #undef G
183 | #undef ROUND
184 |
185 | static int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
186 | {
187 | const unsigned char * in = (const unsigned char *)pin;
188 | if( inlen > 0 )
189 | {
190 | size_t left = S->buflen;
191 | size_t fill = BLAKE2B_BLOCKBYTES - left;
192 | if( inlen > fill )
193 | {
194 | S->buflen = 0;
195 | memcpy( S->buf + left, in, fill ); /* Fill buffer */
196 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
197 | blake2b_compress( S, S->buf ); /* Compress */
198 | in += fill; inlen -= fill;
199 | while(inlen > BLAKE2B_BLOCKBYTES) {
200 | blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
201 | blake2b_compress( S, in );
202 | in += BLAKE2B_BLOCKBYTES;
203 | inlen -= BLAKE2B_BLOCKBYTES;
204 | }
205 | }
206 | memcpy( S->buf + S->buflen, in, inlen );
207 | S->buflen += inlen;
208 | }
209 | return 0;
210 | }
211 |
212 | static int blake2b_final( blake2b_state *S, void *out, size_t outlen )
213 | {
214 | uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
215 | size_t i;
216 |
217 | if( out == NULL || outlen < S->outlen )
218 | return -1;
219 |
220 | if( blake2b_is_lastblock( S ) )
221 | return -1;
222 |
223 | blake2b_increment_counter( S, S->buflen );
224 | blake2b_set_lastblock( S );
225 | memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
226 | blake2b_compress( S, S->buf );
227 |
228 | for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
229 | store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
230 |
231 | memcpy( out, buffer, S->outlen );
232 |
233 | return 0;
234 | }
235 |
236 | /* inlen, at least, should be uint64_t. Others can be size_t. */
237 | void blake2b( void *out, size_t outlen, const void *in, size_t inlen )
238 | {
239 | blake2b_state S[1];
240 |
241 | blake2b_init( S, outlen );
242 |
243 | blake2b_update( S, ( const uint8_t * )in, inlen );
244 | blake2b_final( S, out, outlen );
245 | }
246 |
--------------------------------------------------------------------------------
/src/btrfs-vol.inf:
--------------------------------------------------------------------------------
1 | ;;;
2 | ;;; WinBtrfs
3 | ;;;
4 | ;;;
5 | ;;; Copyright (c) 2016-24 Mark Harmstone
6 | ;;;
7 |
8 | [Version]
9 | Signature = "$Windows NT$"
10 | Class = Volume
11 | ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
12 | Provider = %Me%
13 | DriverVer = 03/15/2024,1.9.0.0
14 | CatalogFile = btrfs.cat
15 | PnpLockdown = 1
16 |
17 | [DestinationDirs]
18 | Btrfs.DriverFiles = 12 ;%windir%\system32\drivers
19 |
20 | [Manufacturer]
21 | %Me%=Standard,NTamd64,NTx86,NTarm,NTarm64
22 |
23 | [Standard.NTamd64]
24 | %VolumeName% = Btrfs_Install, BtrfsVolume
25 | %ControllerName% = Btrfs_Install, ROOT\btrfs
26 |
27 | [Standard.NTx86]
28 | %VolumeName% = Btrfs_Install, BtrfsVolume
29 | %ControllerName% = Btrfs_Install, ROOT\btrfs
30 |
31 | [Standard.NTarm]
32 | %VolumeName% = Btrfs_Install, BtrfsVolume
33 | %ControllerName% = Btrfs_Install, ROOT\btrfs
34 |
35 | [Standard.NTarm64]
36 | %VolumeName% = Btrfs_Install, BtrfsVolume
37 | %ControllerName% = Btrfs_Install, ROOT\btrfs
38 |
39 | [Btrfs_Install]
40 | OptionDesc = %ServiceDescription%
41 | CopyFiles = Btrfs.DriverFiles
42 |
43 | [Btrfs_Install.Services]
44 | AddService = %ServiceName%,2,Btrfs.Service
45 |
46 | ;
47 | ; Services Section
48 | ;
49 |
50 | [Btrfs.Service]
51 | DisplayName = %ServiceName%
52 | Description = %ServiceDescription%
53 | ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\
54 | ServiceType = 1
55 | StartType = 1 ;SERVICE_SYSTEM_START
56 | ErrorControl = 1
57 | LoadOrderGroup = "File System"
58 |
59 | ;
60 | ; Copy Files
61 | ;
62 |
63 | [Btrfs.DriverFiles]
64 | %DriverName%.sys
65 |
66 | [SourceDisksFiles]
67 | btrfs.sys = 1,,
68 |
69 | [SourceDisksNames.x86]
70 | 1 = %DiskId1%,,,\x86
71 |
72 | [SourceDisksNames.amd64]
73 | 1 = %DiskId1%,,,\amd64
74 |
75 | [SourceDisksNames.arm]
76 | 1 = %DiskId1%,,,\arm
77 |
78 | [SourceDisksNames.arm64]
79 | 1 = %DiskId1%,,,\aarch64
80 |
81 | ;;
82 | ;; String Section
83 | ;;
84 |
85 | [Strings]
86 | Me = "Mark Harmstone"
87 | ServiceDescription = "Btrfs driver"
88 | ServiceName = "btrfs"
89 | DriverName = "btrfs"
90 | DiskId1 = "Btrfs Device Installation Disk"
91 | VolumeName = "Btrfs volume"
92 | ControllerName = "Btrfs controller"
93 | REG_EXPAND_SZ = 0x00020000
94 |
--------------------------------------------------------------------------------
/src/btrfs.cdf:
--------------------------------------------------------------------------------
1 | [CatalogHeader]
2 | Name=btrfs.cat
3 | CatalogVersion=1
4 | HashAlgorithms=SHA1
5 | PageHashes=true
6 | EncodingType=0x00010001
7 | CATATTR1=0x10010001:HWID1:btrfsvolume
8 | CATATTR2=0x10010001:HWID2:root\btrfs
9 | CATATTR3=0x10010001:OS:XPX86,XPX64,VistaX86,VistaX64,7X86,7X64,8X86,8X64,8ARM,_v63,_v63_X64,_v63_ARM,_v100,_v100_X64,_v100_X64_22H2,_v100_ARM64_22H2
10 |
11 | [CatalogFiles]
12 | btrfs.inf=btrfs.inf
13 | btrfs.infATTR1=0x10010001:File:btrfs.inf
14 | btrfs.infATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
15 | btrfs-vol.inf=btrfs-vol.inf
16 | btrfs-vol.infATTR1=0x10010001:File:btrfs-vol.inf
17 | btrfs-vol.infATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
18 | aarch64_btrfs.sys=aarch64\btrfs.sys
19 | aarch64_btrfs.sysATTR1=0x10010001:File:btrfs.sys
20 | aarch64_btrfs.sysATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
21 | aarch64_mkbtrfs.exe=aarch64\mkbtrfs.exe
22 | aarch64_mkbtrfs.exeATTR1=0x10010001:File:mkbtrfs.exe
23 | aarch64_mkbtrfs.exeATTR2=0x10010001:OSAttr:2:10.0
24 | aarch64_shellbtrfs.dll=aarch64\shellbtrfs.dll
25 | aarch64_shellbtrfs.dllATTR1=0x10010001:File:shellbtrfs.dll
26 | aarch64_shellbtrfs.dllATTR2=0x10010001:OSAttr:2:10.0
27 | aarch64_ubtrfs.dll=aarch64\ubtrfs.dll
28 | aarch64_ubtrfs.dllATTR1=0x10010001:File:ubtrfs.dll
29 | aarch64_ubtrfs.dllATTR2=0x10010001:OSAttr:2:10.0
30 | amd64_btrfs.sys=amd64\btrfs.sys
31 | amd64_btrfs.sysATTR1=0x10010001:File:btrfs.sys
32 | amd64_btrfs.sysATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
33 | amd64_mkbtrfs.exe=amd64\mkbtrfs.exe
34 | amd64_mkbtrfs.exeATTR1=0x10010001:File:mkbtrfs.exe
35 | amd64_mkbtrfs.exeATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
36 | amd64_shellbtrfs.dll=amd64\shellbtrfs.dll
37 | amd64_shellbtrfs.dllATTR1=0x10010001:File:shellbtrfs.dll
38 | amd64_shellbtrfs.dllATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
39 | amd64_ubtrfs.dll=amd64\ubtrfs.dll
40 | amd64_ubtrfs.dllATTR1=0x10010001:File:ubtrfs.dll
41 | amd64_ubtrfs.dllATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
42 | arm_btrfs.sys=arm\btrfs.sys
43 | arm_btrfs.sysATTR1=0x10010001:File:btrfs.sys
44 | arm_btrfs.sysATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
45 | arm_mkbtrfs.exe=arm\mkbtrfs.exe
46 | arm_mkbtrfs.exeATTR1=0x10010001:File:mkbtrfs.exe
47 | arm_mkbtrfs.exeATTR2=0x10010001:OSAttr:2:6.2,2:6.3
48 | arm_shellbtrfs.dll=arm\shellbtrfs.dll
49 | arm_shellbtrfs.dllATTR1=0x10010001:File:shellbtrfs.dll
50 | arm_shellbtrfs.dllATTR2=0x10010001:OSAttr:2:6.2,2:6.3
51 | arm_ubtrfs.dll=arm\ubtrfs.dll
52 | arm_ubtrfs.dllATTR1=0x10010001:File:ubtrfs.dll
53 | arm_ubtrfs.dllATTR2=0x10010001:OSAttr:2:6.2,2:6.3
54 | x86_btrfs.sys=x86\btrfs.sys
55 | x86_btrfs.sysATTR1=0x10010001:File:btrfs.sys
56 | x86_btrfs.sysATTR2=0x10010001:OSAttr:2:5.1,2:5.2,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
57 | x86_mkbtrfs.exe=x86\mkbtrfs.exe
58 | x86_mkbtrfs.exeATTR1=0x10010001:File:mkbtrfs.exe
59 | x86_mkbtrfs.exeATTR2=0x10010001:OSAttr:2:5.1,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
60 | x86_shellbtrfs.dll=x86\shellbtrfs.dll
61 | x86_shellbtrfs.dllATTR1=0x10010001:File:shellbtrfs.dll
62 | x86_shellbtrfs.dllATTR2=0x10010001:OSAttr:2:5.1,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
63 | x86_ubtrfs.dll=x86\ubtrfs.dll
64 | x86_ubtrfs.dllATTR1=0x10010001:File:ubtrfs.dll
65 | x86_ubtrfs.dllATTR2=0x10010001:OSAttr:2:5.1,2:6.0,2:6.1,2:6.2,2:6.3,2:10.0
66 |
--------------------------------------------------------------------------------
/src/btrfs.inf:
--------------------------------------------------------------------------------
1 | ;;;
2 | ;;; WinBtrfs
3 | ;;;
4 | ;;;
5 | ;;; Copyright (c) 2016-24 Mark Harmstone
6 | ;;;
7 |
8 | [Version]
9 | Signature = "$Windows NT$"
10 | Class = Volume
11 | ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
12 | Provider = %Me%
13 | DriverVer = 03/15/2024,1.9.0.0
14 | CatalogFile = btrfs.cat
15 |
16 | [DestinationDirs]
17 | Btrfs.DriverFiles = 12 ;%windir%\system32\drivers
18 | Btrfs.DllFiles = 11 ;%windir%\system32
19 |
20 | ;;
21 | ;; Default install sections
22 | ;;
23 |
24 | [DefaultInstall.NTamd64]
25 | OptionDesc = %ServiceDescription%
26 | CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
27 | AddReg = shellbtrfs_AddReg
28 | CopyINF = btrfs-vol.inf
29 |
30 | [DefaultInstall.NTx86]
31 | OptionDesc = %ServiceDescription%
32 | CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
33 | AddReg = shellbtrfs_AddReg
34 | CopyINF = btrfs-vol.inf
35 |
36 | [DefaultInstall.NTarm]
37 | OptionDesc = %ServiceDescription%
38 | CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
39 | AddReg = shellbtrfs_AddReg
40 | CopyINF = btrfs-vol.inf
41 |
42 | [DefaultInstall.NTarm64]
43 | OptionDesc = %ServiceDescription%
44 | CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
45 | AddReg = shellbtrfs_AddReg
46 | CopyINF = btrfs-vol.inf
47 |
48 | [DefaultInstall.NTamd64.Services]
49 | AddService = %ServiceName%,0x802,Btrfs.Service
50 |
51 | [DefaultInstall.NTx86.Services]
52 | AddService = %ServiceName%,0x802,Btrfs.Service
53 |
54 | [DefaultInstall.NTarm.Services]
55 | AddService = %ServiceName%,0x802,Btrfs.Service
56 |
57 | [DefaultInstall.NTarm64.Services]
58 | AddService = %ServiceName%,0x802,Btrfs.Service
59 |
60 | ;
61 | ; Services Section
62 | ;
63 |
64 | [Btrfs.Service]
65 | DisplayName = %ServiceName%
66 | Description = %ServiceDescription%
67 | ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\
68 | ServiceType = 1
69 | StartType = 1 ;SERVICE_SYSTEM_START
70 | ErrorControl = 1
71 | LoadOrderGroup = "File System"
72 |
73 | ;
74 | ; Copy Files
75 | ;
76 |
77 | [Btrfs.DriverFiles]
78 | %DriverName%.sys
79 |
80 | [Btrfs.DllFiles]
81 | shellbtrfs.dll
82 | ubtrfs.dll
83 | mkbtrfs.exe
84 |
85 | [SourceDisksFiles]
86 | btrfs.sys = 1,,
87 | shellbtrfs.dll = 1,,
88 | ubtrfs.dll = 1,,
89 | mkbtrfs.exe = 1,,
90 |
91 | [SourceDisksNames.x86]
92 | 1 = %DiskId1%,,,\x86
93 |
94 | [SourceDisksNames.amd64]
95 | 1 = %DiskId1%,,,\amd64
96 |
97 | [SourceDisksNames.arm]
98 | 1 = %DiskId1%,,,\arm
99 |
100 | [SourceDisksNames.arm64]
101 | 1 = %DiskId1%,,,\aarch64
102 |
103 | [shellbtrfs_AddReg]
104 | HKCR,*\ShellEx\PropertySheetHandlers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F2}"
105 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F0},,,"WinBtrfs shell extension (icon handler)"
106 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F0}\InprocServer32,,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\shellbtrfs.dll"
107 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F0}\InprocServer32,ThreadingModel,,"Apartment"
108 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F1},,,"WinBtrfs shell extension (context menu)"
109 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F1}\InprocServer32,,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\shellbtrfs.dll"
110 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F1}\InprocServer32,ThreadingModel,,"Apartment"
111 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F2},,,"WinBtrfs shell extension (property sheet)"
112 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F2}\InprocServer32,,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\shellbtrfs.dll"
113 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F2}\InprocServer32,ThreadingModel,,"Apartment"
114 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F3},,,"WinBtrfs shell extension (volume property sheet)"
115 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F3}\InprocServer32,,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\shellbtrfs.dll"
116 | HKCR,CLSID\{2690B74F-F353-422D-BB12-401581EEF8F3}\InprocServer32,ThreadingModel,,"Apartment"
117 | HKCR,Directory\Background\ShellEx\ContextMenuHandlers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F1}"
118 | HKCR,Drive\ShellEx\PropertySheetHandlers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F3}"
119 | HKCR,Folder\ShellEx\ContextMenuHandlers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F1}"
120 | HKCR,Folder\ShellEx\PropertySheetHandlers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F2}"
121 | ;HKLM,Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\WinBtrfs,,,"{2690B74F-F353-422D-BB12-401581EEF8F0}"
122 |
123 | ;;
124 | ;; String Section
125 | ;;
126 |
127 | [Strings]
128 | Me = "Mark Harmstone"
129 | ServiceDescription = "Btrfs driver"
130 | ServiceName = "btrfs"
131 | DriverName = "btrfs"
132 | DiskId1 = "Btrfs Device Installation Disk"
133 | VolumeName = "Btrfs volume"
134 | ControllerName = "Btrfs controller"
135 | REG_EXPAND_SZ = 0x00020000
136 |
--------------------------------------------------------------------------------
/src/btrfs.rc.in:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "@CMAKE_CURRENT_SOURCE_DIR@/src/resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (United Kingdom) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Version
51 | //
52 |
53 | VS_VERSION_INFO VERSIONINFO
54 | FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
55 | PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
56 | FILEFLAGSMASK 0x17L
57 | #ifdef _DEBUG
58 | FILEFLAGS 0x1L
59 | #else
60 | FILEFLAGS 0x0L
61 | #endif
62 | FILEOS 0x4L
63 | FILETYPE 0x1L
64 | FILESUBTYPE 0x0L
65 | BEGIN
66 | BLOCK "StringFileInfo"
67 | BEGIN
68 | BLOCK "080904b0"
69 | BEGIN
70 | VALUE "FileDescription", "WinBtrfs"
71 | VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
72 | VALUE "InternalName", "btrfs"
73 | VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-24"
74 | VALUE "OriginalFilename", "btrfs.sys"
75 | VALUE "ProductName", "WinBtrfs"
76 | VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
77 | END
78 | END
79 | BLOCK "VarFileInfo"
80 | BEGIN
81 | VALUE "Translation", 0x809, 1200
82 | END
83 | END
84 |
85 | #endif // English (United Kingdom) resources
86 | /////////////////////////////////////////////////////////////////////////////
87 |
88 |
89 |
90 | #ifndef APSTUDIO_INVOKED
91 | /////////////////////////////////////////////////////////////////////////////
92 | //
93 | // Generated from the TEXTINCLUDE 3 resource.
94 | //
95 |
96 |
97 | /////////////////////////////////////////////////////////////////////////////
98 | #endif // not APSTUDIO_INVOKED
99 |
100 |
--------------------------------------------------------------------------------
/src/btrfsioctl.h:
--------------------------------------------------------------------------------
1 | // No copyright claimed in this file - do what you want with it.
2 |
3 | #pragma once
4 |
5 | #include "btrfs.h"
6 |
7 | #define FSCTL_BTRFS_GET_FILE_IDS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x829, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
8 | #define FSCTL_BTRFS_CREATE_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82a, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
9 | #define FSCTL_BTRFS_CREATE_SNAPSHOT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82b, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
10 | #define FSCTL_BTRFS_GET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82c, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
11 | #define FSCTL_BTRFS_SET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82d, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
12 | #define FSCTL_BTRFS_GET_DEVICES CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82e, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
13 | #define FSCTL_BTRFS_GET_USAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82f, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
14 | #define FSCTL_BTRFS_START_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
15 | #define FSCTL_BTRFS_QUERY_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x831, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
16 | #define FSCTL_BTRFS_PAUSE_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x832, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
17 | #define FSCTL_BTRFS_RESUME_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x833, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
18 | #define FSCTL_BTRFS_STOP_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x834, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
19 | #define FSCTL_BTRFS_ADD_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x835, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
20 | #define FSCTL_BTRFS_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x836, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
21 | #define IOCTL_BTRFS_QUERY_FILESYSTEMS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x837, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
22 | #define FSCTL_BTRFS_GET_UUID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x838, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
23 | #define FSCTL_BTRFS_START_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x839, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
24 | #define FSCTL_BTRFS_QUERY_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
25 | #define FSCTL_BTRFS_PAUSE_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83b, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
26 | #define FSCTL_BTRFS_RESUME_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83c, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
27 | #define FSCTL_BTRFS_STOP_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83d, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
28 | #define IOCTL_BTRFS_PROBE_VOLUME CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83e, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
29 | #define FSCTL_BTRFS_RESET_STATS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83f, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
30 | #define FSCTL_BTRFS_MKNOD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x840, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
31 | #define FSCTL_BTRFS_RECEIVED_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x841, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
32 | #define FSCTL_BTRFS_GET_XATTRS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x842, METHOD_BUFFERED, FILE_ANY_ACCESS)
33 | #define FSCTL_BTRFS_SET_XATTR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x843, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
34 | #define FSCTL_BTRFS_RESERVE_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x844, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
35 | #define FSCTL_BTRFS_FIND_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x845, METHOD_BUFFERED, FILE_ANY_ACCESS)
36 | #define FSCTL_BTRFS_SEND_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x846, METHOD_BUFFERED, FILE_ANY_ACCESS)
37 | #define FSCTL_BTRFS_READ_SEND_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x847, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
38 | #define FSCTL_BTRFS_RESIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x848, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
39 | #define IOCTL_BTRFS_UNLOAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x849, METHOD_NEITHER, FILE_ANY_ACCESS)
40 | #define FSCTL_BTRFS_GET_CSUM_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x84a, METHOD_BUFFERED, FILE_READ_ACCESS)
41 |
42 | typedef struct {
43 | uint64_t subvol;
44 | uint64_t inode;
45 | BOOL top;
46 | } btrfs_get_file_ids;
47 |
48 | typedef struct {
49 | HANDLE subvol;
50 | BOOL readonly;
51 | BOOL posix;
52 | uint16_t namelen;
53 | WCHAR name[1];
54 | } btrfs_create_snapshot;
55 |
56 | typedef struct {
57 | void* POINTER_32 subvol;
58 | BOOL readonly;
59 | BOOL posix;
60 | uint16_t namelen;
61 | WCHAR name[1];
62 | } btrfs_create_snapshot32;
63 |
64 | #define BTRFS_COMPRESSION_ANY 0
65 | #define BTRFS_COMPRESSION_ZLIB 1
66 | #define BTRFS_COMPRESSION_LZO 2
67 | #define BTRFS_COMPRESSION_ZSTD 3
68 |
69 | typedef struct {
70 | uint64_t subvol;
71 | uint64_t inode;
72 | BOOL top;
73 | uint8_t type;
74 | uint32_t st_uid;
75 | uint32_t st_gid;
76 | uint32_t st_mode;
77 | uint64_t st_rdev;
78 | uint64_t flags;
79 | uint32_t inline_length;
80 | uint64_t disk_size_uncompressed;
81 | uint64_t disk_size_zlib;
82 | uint64_t disk_size_lzo;
83 | uint8_t compression_type;
84 | uint64_t disk_size_zstd;
85 | uint64_t sparse_size;
86 | uint32_t num_extents;
87 | } btrfs_inode_info;
88 |
89 | typedef struct {
90 | uint64_t flags;
91 | BOOL flags_changed;
92 | uint32_t st_uid;
93 | BOOL uid_changed;
94 | uint32_t st_gid;
95 | BOOL gid_changed;
96 | uint32_t st_mode;
97 | BOOL mode_changed;
98 | uint8_t compression_type;
99 | BOOL compression_type_changed;
100 | } btrfs_set_inode_info;
101 |
102 | typedef struct {
103 | uint32_t next_entry;
104 | uint64_t dev_id;
105 | uint64_t size;
106 | uint64_t max_size;
107 | BOOL readonly;
108 | BOOL missing;
109 | ULONG device_number;
110 | ULONG partition_number;
111 | uint64_t stats[5];
112 | USHORT namelen;
113 | WCHAR name[1];
114 | } btrfs_device;
115 |
116 | typedef struct {
117 | uint64_t dev_id;
118 | uint64_t alloc;
119 | } btrfs_usage_device;
120 |
121 | typedef struct {
122 | uint32_t next_entry;
123 | uint64_t type;
124 | uint64_t size;
125 | uint64_t used;
126 | uint64_t num_devices;
127 | btrfs_usage_device devices[1];
128 | } btrfs_usage;
129 |
130 | #define BTRFS_BALANCE_OPTS_ENABLED 0x001
131 | #define BTRFS_BALANCE_OPTS_PROFILES 0x002
132 | #define BTRFS_BALANCE_OPTS_DEVID 0x004
133 | #define BTRFS_BALANCE_OPTS_DRANGE 0x008
134 | #define BTRFS_BALANCE_OPTS_VRANGE 0x010
135 | #define BTRFS_BALANCE_OPTS_LIMIT 0x020
136 | #define BTRFS_BALANCE_OPTS_STRIPES 0x040
137 | #define BTRFS_BALANCE_OPTS_USAGE 0x080
138 | #define BTRFS_BALANCE_OPTS_CONVERT 0x100
139 | #define BTRFS_BALANCE_OPTS_SOFT 0x200
140 |
141 | #define BLOCK_FLAG_SINGLE 0x1000000000000 // only used in balance
142 |
143 | typedef struct {
144 | uint64_t flags;
145 | uint64_t profiles;
146 | uint64_t devid;
147 | uint64_t drange_start;
148 | uint64_t drange_end;
149 | uint64_t vrange_start;
150 | uint64_t vrange_end;
151 | uint64_t limit_start;
152 | uint64_t limit_end;
153 | uint16_t stripes_start;
154 | uint16_t stripes_end;
155 | uint8_t usage_start;
156 | uint8_t usage_end;
157 | uint64_t convert;
158 | } btrfs_balance_opts;
159 |
160 | #define BTRFS_BALANCE_STOPPED 0
161 | #define BTRFS_BALANCE_RUNNING 1
162 | #define BTRFS_BALANCE_PAUSED 2
163 | #define BTRFS_BALANCE_REMOVAL 4
164 | #define BTRFS_BALANCE_ERROR 8
165 | #define BTRFS_BALANCE_SHRINKING 16
166 |
167 | typedef struct {
168 | uint32_t status;
169 | uint64_t chunks_left;
170 | uint64_t total_chunks;
171 | NTSTATUS error;
172 | btrfs_balance_opts data_opts;
173 | btrfs_balance_opts metadata_opts;
174 | btrfs_balance_opts system_opts;
175 | } btrfs_query_balance;
176 |
177 | typedef struct {
178 | btrfs_balance_opts opts[3];
179 | } btrfs_start_balance;
180 |
181 | typedef struct {
182 | uint8_t uuid[16];
183 | BOOL missing;
184 | USHORT name_length;
185 | WCHAR name[1];
186 | } btrfs_filesystem_device;
187 |
188 | typedef struct {
189 | uint32_t next_entry;
190 | uint8_t uuid[16];
191 | uint32_t num_devices;
192 | btrfs_filesystem_device device;
193 | } btrfs_filesystem;
194 |
195 | #define BTRFS_SCRUB_STOPPED 0
196 | #define BTRFS_SCRUB_RUNNING 1
197 | #define BTRFS_SCRUB_PAUSED 2
198 |
199 | typedef struct {
200 | uint32_t next_entry;
201 | uint64_t address;
202 | uint64_t device;
203 | BOOL recovered;
204 | BOOL is_metadata;
205 | BOOL parity;
206 |
207 | union {
208 | struct {
209 | uint64_t subvol;
210 | uint64_t offset;
211 | uint16_t filename_length;
212 | WCHAR filename[1];
213 | } data;
214 |
215 | struct {
216 | uint64_t root;
217 | uint8_t level;
218 | KEY firstitem;
219 | } metadata;
220 | };
221 | } btrfs_scrub_error;
222 |
223 | typedef struct {
224 | uint32_t status;
225 | LARGE_INTEGER start_time;
226 | LARGE_INTEGER finish_time;
227 | uint64_t chunks_left;
228 | uint64_t total_chunks;
229 | uint64_t data_scrubbed;
230 | uint64_t duration;
231 | NTSTATUS error;
232 | uint32_t num_errors;
233 | btrfs_scrub_error errors;
234 | } btrfs_query_scrub;
235 |
236 | typedef struct {
237 | uint64_t inode;
238 | uint8_t type;
239 | uint64_t st_rdev;
240 | uint16_t namelen;
241 | WCHAR name[1];
242 | } btrfs_mknod;
243 |
244 | typedef struct {
245 | uint64_t generation;
246 | BTRFS_UUID uuid;
247 | } btrfs_received_subvol;
248 |
249 | typedef struct {
250 | USHORT namelen;
251 | USHORT valuelen;
252 | char data[1];
253 | } btrfs_set_xattr;
254 |
255 | typedef struct {
256 | BOOL readonly;
257 | BOOL posix;
258 | USHORT namelen;
259 | WCHAR name[1];
260 | } btrfs_create_subvol;
261 |
262 | typedef struct {
263 | BTRFS_UUID uuid;
264 | uint64_t ctransid;
265 | } btrfs_find_subvol;
266 |
267 | typedef struct {
268 | HANDLE parent;
269 | ULONG num_clones;
270 | HANDLE clones[1];
271 | } btrfs_send_subvol;
272 |
273 | typedef struct {
274 | void* POINTER_32 parent;
275 | ULONG num_clones;
276 | void* POINTER_32 clones[1];
277 | } btrfs_send_subvol32;
278 |
279 | typedef struct {
280 | uint64_t device;
281 | uint64_t size;
282 | } btrfs_resize;
283 |
284 | typedef struct {
285 | uint8_t csum_type;
286 | uint8_t csum_length;
287 | uint64_t num_sectors;
288 | uint8_t data[1];
289 | } btrfs_csum_info;
290 |
--------------------------------------------------------------------------------
/src/cache.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "btrfs_drv.h"
19 |
20 | CACHE_MANAGER_CALLBACKS cache_callbacks;
21 |
22 | static BOOLEAN __stdcall acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) {
23 | PFILE_OBJECT FileObject = Context;
24 | fcb* fcb = FileObject->FsContext;
25 |
26 | TRACE("(%p, %u)\n", Context, Wait);
27 |
28 | if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait))
29 | return false;
30 |
31 | if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) {
32 | ExReleaseResourceLite(&fcb->Vcb->tree_lock);
33 | return false;
34 | }
35 |
36 | fcb->lazy_writer_thread = KeGetCurrentThread();
37 |
38 | IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
39 |
40 | return true;
41 | }
42 |
43 | static void __stdcall release_from_lazy_write(PVOID Context) {
44 | PFILE_OBJECT FileObject = Context;
45 | fcb* fcb = FileObject->FsContext;
46 |
47 | TRACE("(%p)\n", Context);
48 |
49 | fcb->lazy_writer_thread = NULL;
50 |
51 | ExReleaseResourceLite(fcb->Header.Resource);
52 |
53 | ExReleaseResourceLite(&fcb->Vcb->tree_lock);
54 |
55 | if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
56 | IoSetTopLevelIrp(NULL);
57 | }
58 |
59 | static BOOLEAN __stdcall acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) {
60 | PFILE_OBJECT FileObject = Context;
61 | fcb* fcb = FileObject->FsContext;
62 |
63 | TRACE("(%p, %u)\n", Context, Wait);
64 |
65 | if (!ExAcquireResourceSharedLite(fcb->Header.Resource, Wait))
66 | return false;
67 |
68 | IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
69 |
70 | return true;
71 | }
72 |
73 | static void __stdcall release_from_read_ahead(PVOID Context) {
74 | PFILE_OBJECT FileObject = Context;
75 | fcb* fcb = FileObject->FsContext;
76 |
77 | TRACE("(%p)\n", Context);
78 |
79 | ExReleaseResourceLite(fcb->Header.Resource);
80 |
81 | if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
82 | IoSetTopLevelIrp(NULL);
83 | }
84 |
85 | void init_cache() {
86 | cache_callbacks.AcquireForLazyWrite = acquire_for_lazy_write;
87 | cache_callbacks.ReleaseFromLazyWrite = release_from_lazy_write;
88 | cache_callbacks.AcquireForReadAhead = acquire_for_read_ahead;
89 | cache_callbacks.ReleaseFromReadAhead = release_from_read_ahead;
90 | }
91 |
--------------------------------------------------------------------------------
/src/calcthread.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "btrfs_drv.h"
19 | #include "zstd/lib/common/xxhash.h"
20 | #include "crc32c.h"
21 |
22 | void calc_thread_main(device_extension* Vcb, calc_job* cj) {
23 | while (true) {
24 | KIRQL irql;
25 | calc_job* cj2;
26 | uint8_t* src;
27 | void* dest;
28 | bool last_one = false;
29 |
30 | KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
31 |
32 | if (cj && cj->not_started == 0) {
33 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
34 | break;
35 | }
36 |
37 | if (cj)
38 | cj2 = cj;
39 | else {
40 | if (IsListEmpty(&Vcb->calcthreads.job_list)) {
41 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
42 | break;
43 | }
44 |
45 | cj2 = CONTAINING_RECORD(Vcb->calcthreads.job_list.Flink, calc_job, list_entry);
46 | }
47 |
48 | src = cj2->in;
49 | dest = cj2->out;
50 |
51 | switch (cj2->type) {
52 | case calc_thread_crc32c:
53 | case calc_thread_xxhash:
54 | case calc_thread_sha256:
55 | case calc_thread_blake2:
56 | cj2->in = (uint8_t*)cj2->in + Vcb->superblock.sector_size;
57 | cj2->out = (uint8_t*)cj2->out + Vcb->csum_size;
58 | break;
59 |
60 | default:
61 | break;
62 | }
63 |
64 | cj2->not_started--;
65 |
66 | if (cj2->not_started == 0) {
67 | RemoveEntryList(&cj2->list_entry);
68 | last_one = true;
69 | }
70 |
71 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
72 |
73 | switch (cj2->type) {
74 | case calc_thread_crc32c:
75 | *(uint32_t*)dest = ~calc_crc32c(0xffffffff, src, Vcb->superblock.sector_size);
76 | break;
77 |
78 | case calc_thread_xxhash:
79 | *(uint64_t*)dest = XXH64(src, Vcb->superblock.sector_size, 0);
80 | break;
81 |
82 | case calc_thread_sha256:
83 | calc_sha256(dest, src, Vcb->superblock.sector_size);
84 | break;
85 |
86 | case calc_thread_blake2:
87 | blake2b(dest, BLAKE2_HASH_SIZE, src, Vcb->superblock.sector_size);
88 | break;
89 |
90 | case calc_thread_decomp_zlib:
91 | cj2->Status = zlib_decompress(src, cj2->inlen, dest, cj2->outlen);
92 |
93 | if (!NT_SUCCESS(cj2->Status))
94 | ERR("zlib_decompress returned %08lx\n", cj2->Status);
95 | break;
96 |
97 | case calc_thread_decomp_lzo:
98 | cj2->Status = lzo_decompress(src, cj2->inlen, dest, cj2->outlen, cj2->off);
99 |
100 | if (!NT_SUCCESS(cj2->Status))
101 | ERR("lzo_decompress returned %08lx\n", cj2->Status);
102 | break;
103 |
104 | case calc_thread_decomp_zstd:
105 | cj2->Status = zstd_decompress(src, cj2->inlen, dest, cj2->outlen);
106 |
107 | if (!NT_SUCCESS(cj2->Status))
108 | ERR("zstd_decompress returned %08lx\n", cj2->Status);
109 | break;
110 |
111 | case calc_thread_comp_zlib:
112 | cj2->Status = zlib_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zlib_level, &cj2->space_left);
113 |
114 | if (!NT_SUCCESS(cj2->Status))
115 | ERR("zlib_compress returned %08lx\n", cj2->Status);
116 | break;
117 |
118 | case calc_thread_comp_lzo:
119 | cj2->Status = lzo_compress(src, cj2->inlen, dest, cj2->outlen, &cj2->space_left);
120 |
121 | if (!NT_SUCCESS(cj2->Status))
122 | ERR("lzo_compress returned %08lx\n", cj2->Status);
123 | break;
124 |
125 | case calc_thread_comp_zstd:
126 | cj2->Status = zstd_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zstd_level, &cj2->space_left);
127 |
128 | if (!NT_SUCCESS(cj2->Status))
129 | ERR("zstd_compress returned %08lx\n", cj2->Status);
130 | break;
131 | }
132 |
133 | if (InterlockedDecrement(&cj2->left) == 0)
134 | KeSetEvent(&cj2->event, 0, false);
135 |
136 | if (last_one)
137 | break;
138 | }
139 | }
140 |
141 | void do_calc_job(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum) {
142 | KIRQL irql;
143 | calc_job cj;
144 |
145 | cj.in = data;
146 | cj.out = csum;
147 | cj.left = cj.not_started = sectors;
148 |
149 | switch (Vcb->superblock.csum_type) {
150 | case CSUM_TYPE_CRC32C:
151 | cj.type = calc_thread_crc32c;
152 | break;
153 |
154 | case CSUM_TYPE_XXHASH:
155 | cj.type = calc_thread_xxhash;
156 | break;
157 |
158 | case CSUM_TYPE_SHA256:
159 | cj.type = calc_thread_sha256;
160 | break;
161 |
162 | case CSUM_TYPE_BLAKE2:
163 | cj.type = calc_thread_blake2;
164 | break;
165 | }
166 |
167 | KeInitializeEvent(&cj.event, NotificationEvent, false);
168 |
169 | KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
170 |
171 | InsertTailList(&Vcb->calcthreads.job_list, &cj.list_entry);
172 |
173 | KeSetEvent(&Vcb->calcthreads.event, 0, false);
174 | KeClearEvent(&Vcb->calcthreads.event);
175 |
176 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
177 |
178 | calc_thread_main(Vcb, &cj);
179 |
180 | KeWaitForSingleObject(&cj.event, Executive, KernelMode, false, NULL);
181 | }
182 |
183 | NTSTATUS add_calc_job_decomp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
184 | void* out, unsigned int outlen, unsigned int off, calc_job** pcj) {
185 | calc_job* cj;
186 | KIRQL irql;
187 |
188 | cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG);
189 | if (!cj) {
190 | ERR("out of memory\n");
191 | return STATUS_INSUFFICIENT_RESOURCES;
192 | }
193 |
194 | cj->in = in;
195 | cj->inlen = inlen;
196 | cj->out = out;
197 | cj->outlen = outlen;
198 | cj->off = off;
199 | cj->left = cj->not_started = 1;
200 | cj->Status = STATUS_SUCCESS;
201 |
202 | switch (compression) {
203 | case BTRFS_COMPRESSION_ZLIB:
204 | cj->type = calc_thread_decomp_zlib;
205 | break;
206 |
207 | case BTRFS_COMPRESSION_LZO:
208 | cj->type = calc_thread_decomp_lzo;
209 | break;
210 |
211 | case BTRFS_COMPRESSION_ZSTD:
212 | cj->type = calc_thread_decomp_zstd;
213 | break;
214 |
215 | default:
216 | ERR("unexpected compression type %x\n", compression);
217 | ExFreePool(cj);
218 | return STATUS_NOT_SUPPORTED;
219 | }
220 |
221 | KeInitializeEvent(&cj->event, NotificationEvent, false);
222 |
223 | KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
224 |
225 | InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
226 |
227 | KeSetEvent(&Vcb->calcthreads.event, 0, false);
228 | KeClearEvent(&Vcb->calcthreads.event);
229 |
230 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
231 |
232 | *pcj = cj;
233 |
234 | return STATUS_SUCCESS;
235 | }
236 |
237 | NTSTATUS add_calc_job_comp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
238 | void* out, unsigned int outlen, calc_job** pcj) {
239 | calc_job* cj;
240 | KIRQL irql;
241 |
242 | cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG);
243 | if (!cj) {
244 | ERR("out of memory\n");
245 | return STATUS_INSUFFICIENT_RESOURCES;
246 | }
247 |
248 | cj->in = in;
249 | cj->inlen = inlen;
250 | cj->out = out;
251 | cj->outlen = outlen;
252 | cj->left = cj->not_started = 1;
253 | cj->Status = STATUS_SUCCESS;
254 |
255 | switch (compression) {
256 | case BTRFS_COMPRESSION_ZLIB:
257 | cj->type = calc_thread_comp_zlib;
258 | break;
259 |
260 | case BTRFS_COMPRESSION_LZO:
261 | cj->type = calc_thread_comp_lzo;
262 | break;
263 |
264 | case BTRFS_COMPRESSION_ZSTD:
265 | cj->type = calc_thread_comp_zstd;
266 | break;
267 |
268 | default:
269 | ERR("unexpected compression type %x\n", compression);
270 | ExFreePool(cj);
271 | return STATUS_NOT_SUPPORTED;
272 | }
273 |
274 | KeInitializeEvent(&cj->event, NotificationEvent, false);
275 |
276 | KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
277 |
278 | InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
279 |
280 | KeSetEvent(&Vcb->calcthreads.event, 0, false);
281 | KeClearEvent(&Vcb->calcthreads.event);
282 |
283 | KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
284 |
285 | *pcj = cj;
286 |
287 | return STATUS_SUCCESS;
288 | }
289 |
290 | _Function_class_(KSTART_ROUTINE)
291 | void __stdcall calc_thread(void* context) {
292 | drv_calc_thread* thread = context;
293 | device_extension* Vcb = thread->DeviceObject->DeviceExtension;
294 |
295 | ObReferenceObject(thread->DeviceObject);
296 |
297 | KeSetSystemAffinityThread((KAFFINITY)1 << thread->number);
298 |
299 | while (true) {
300 | KeWaitForSingleObject(&Vcb->calcthreads.event, Executive, KernelMode, false, NULL);
301 |
302 | calc_thread_main(Vcb, NULL);
303 |
304 | if (thread->quit)
305 | break;
306 | }
307 |
308 | ObDereferenceObject(thread->DeviceObject);
309 |
310 | KeSetEvent(&thread->finished, 0, false);
311 |
312 | PsTerminateSystemThread(STATUS_SUCCESS);
313 | }
314 |
--------------------------------------------------------------------------------
/src/crc32c-aarch64.asm:
--------------------------------------------------------------------------------
1 | AREA .text, CODE, READONLY
2 |
3 | GLOBAL calc_crc32c_hw
4 |
5 | ; uint32_t calc_crc32c_hw(uint32_t seed, const uint8_t* buf, uint32_t len);
6 | calc_crc32c_hw
7 | ; w0 = crc / seed
8 | ; x1 = buf
9 | ; w2 = len
10 | ; x3 = scratch
11 |
12 | cmp w2, #8
13 | b.lt crchw_stragglers
14 |
15 | ldr x3, [x1]
16 | crc32cx w0, w0, x3
17 |
18 | add x1, x1, #8
19 | sub w2, w2, #8
20 | b calc_crc32c_hw
21 |
22 | crchw_stragglers
23 | cmp w2, #4
24 | b.lt crchw_stragglers2
25 |
26 | ldr w3, [x1]
27 | crc32cw w0, w0, w3
28 |
29 | add x1, x1, #4
30 | sub w2, w2, #4
31 |
32 | crchw_stragglers2
33 | cmp w2, #2
34 | b.lt crchw_stragglers3
35 |
36 | ldrh w3, [x1]
37 | crc32ch w0, w0, w3
38 |
39 | add x1, x1, #2
40 | sub w2, w2, #2
41 |
42 | crchw_stragglers3
43 | cmp w2, #0
44 | b.eq crchw_end
45 |
46 | ldrb w3, [x1]
47 | crc32cb w0, w0, w3
48 |
49 | crchw_end
50 | ret
51 |
52 | END
53 |
--------------------------------------------------------------------------------
/src/crc32c-gas.S:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2020
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | .intel_syntax noprefix
19 |
20 | #ifdef __x86_64__
21 |
22 | .extern crctable
23 | .global calc_crc32c_sw
24 |
25 | /* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
26 |
27 | calc_crc32c_sw:
28 |
29 | /* rax = crc / seed
30 | * rdx = buf
31 | * r8 = len
32 | * rcx = tmp
33 | * r10 = tmp2 */
34 |
35 | mov rax, rcx
36 |
37 | crcloop:
38 | test r8, r8
39 | jz crcend
40 |
41 | mov rcx, rax
42 | shr rcx, 8
43 | mov r10b, byte ptr [rdx]
44 | xor al, r10b
45 | and rax, 255
46 | shl rax, 2
47 | movabs r10, offset crctable
48 | mov eax, dword ptr [r10 + rax]
49 | xor rax, rcx
50 |
51 | inc rdx
52 | dec r8
53 |
54 | jmp crcloop
55 |
56 | crcend:
57 | ret
58 |
59 | /****************************************************/
60 |
61 | /* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
62 |
63 | .global calc_crc32c_hw
64 |
65 | calc_crc32c_hw:
66 |
67 | /* rax = crc / seed
68 | * rdx = buf
69 | * r8 = len */
70 |
71 | mov rax, rcx
72 |
73 | crchw_loop:
74 | cmp r8, 8
75 | jl crchw_stragglers
76 |
77 | crc32 rax, qword ptr [rdx]
78 |
79 | add rdx, 8
80 | sub r8, 8
81 | jmp crchw_loop
82 |
83 | crchw_stragglers:
84 | cmp r8, 4
85 | jl crchw_stragglers2
86 |
87 | crc32 eax, dword ptr [rdx]
88 |
89 | add rdx, 4
90 | sub r8, 4
91 |
92 | crchw_stragglers2:
93 | cmp r8, 2
94 | jl crchw_stragglers3
95 |
96 | crc32 eax, word ptr [rdx]
97 |
98 | add rdx, 2
99 | sub r8, 2
100 |
101 | crchw_stragglers3:
102 | test r8, r8
103 | jz crchw_end
104 |
105 | crc32 eax, byte ptr [rdx]
106 | inc rdx
107 | dec r8
108 | jmp crchw_stragglers3
109 |
110 | crchw_end:
111 | ret
112 |
113 | #elif defined(_X86_)
114 |
115 | .extern _crctable
116 | .global _calc_crc32c_sw@12
117 | .global _calc_crc32c_hw@12
118 |
119 | /* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
120 |
121 | _calc_crc32c_sw@12:
122 |
123 | push ebp
124 | mov ebp, esp
125 |
126 | push esi
127 | push ebx
128 |
129 | mov eax, [ebp+8]
130 | mov edx, [ebp+12]
131 | mov ebx, [ebp+16]
132 |
133 | /* eax = crc / seed
134 | * ebx = len
135 | * esi = tmp
136 | * edx = buf
137 | * ecx = tmp2 */
138 |
139 | crcloop:
140 | test ebx, ebx
141 | jz crcend
142 |
143 | mov esi, eax
144 | shr esi, 8
145 | mov cl, byte ptr [edx]
146 | xor al, cl
147 | and eax, 255
148 | shl eax, 2
149 | mov eax, [_crctable + eax]
150 | xor eax, esi
151 |
152 | inc edx
153 | dec ebx
154 |
155 | jmp crcloop
156 |
157 | crcend:
158 | pop ebx
159 | pop esi
160 |
161 | pop ebp
162 |
163 | ret 12
164 |
165 | /****************************************************/
166 |
167 | /* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
168 |
169 | _calc_crc32c_hw@12:
170 |
171 | push ebp
172 | mov ebp, esp
173 |
174 | mov eax, [ebp+8]
175 | mov edx, [ebp+12]
176 | mov ecx, [ebp+16]
177 |
178 | /* eax = crc / seed
179 | * ecx = len
180 | * edx = buf */
181 |
182 | crchw_loop:
183 | cmp ecx, 4
184 | jl crchw_stragglers
185 |
186 | crc32 eax, dword ptr [edx]
187 |
188 | add edx, 4
189 | sub ecx, 4
190 | jmp crchw_loop
191 |
192 | crchw_stragglers:
193 | cmp ecx, 2
194 | jl crchw_stragglers2
195 |
196 | crc32 eax, word ptr [edx]
197 |
198 | add edx, 2
199 | sub ecx, 2
200 |
201 | crchw_stragglers2:
202 | test ecx, ecx
203 | jz crchw_end
204 |
205 | crc32 eax, byte ptr [edx]
206 | inc edx
207 | dec ecx
208 | jmp crchw_stragglers2
209 |
210 | crchw_end:
211 | pop ebp
212 |
213 | ret 12
214 |
215 | #endif
216 |
--------------------------------------------------------------------------------
/src/crc32c-masm.asm:
--------------------------------------------------------------------------------
1 | ; Copyright (c) Mark Harmstone 2020
2 | ;
3 | ; This file is part of WinBtrfs.
4 | ;
5 | ; WinBtrfs is free software: you can redistribute it and/or modify
6 | ; it under the terms of the GNU Lesser General Public Licence as published by
7 | ; the Free Software Foundation, either version 3 of the Licence, or
8 | ; (at your option) any later version.
9 | ;
10 | ; WinBtrfs is distributed in the hope that it will be useful,
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ; GNU Lesser General Public Licence for more details.
14 | ;
15 | ; You should have received a copy of the GNU Lesser General Public Licence
16 | ; along with WinBtrfs. If not, see .
17 |
18 | IFDEF RAX
19 | ELSE
20 | .686P
21 | ENDIF
22 |
23 | _TEXT SEGMENT
24 |
25 | IFDEF RAX
26 |
27 | EXTERN crctable:qword
28 |
29 | PUBLIC calc_crc32c_sw
30 |
31 | ; uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
32 |
33 | calc_crc32c_sw:
34 |
35 | ; rax = crc / seed
36 | ; rdx = buf
37 | ; r8 = len
38 | ; rcx = tmp
39 | ; r10 = tmp2
40 |
41 | mov rax, rcx
42 |
43 | crcloop:
44 | test r8, r8
45 | jz crcend
46 |
47 | mov rcx, rax
48 | shr rcx, 8
49 | mov r10b, byte ptr [rdx]
50 | xor al, r10b
51 | and rax, 255
52 | shl rax, 2
53 | mov r10, offset crctable
54 | mov eax, dword ptr [r10 + rax]
55 | xor rax, rcx
56 |
57 | inc rdx
58 | dec r8
59 |
60 | jmp crcloop
61 |
62 | crcend:
63 | ret
64 |
65 | ; ****************************************************
66 |
67 | ; uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
68 |
69 | PUBLIC calc_crc32c_hw
70 |
71 | calc_crc32c_hw:
72 |
73 | ; rax = crc / seed
74 | ; rdx = buf
75 | ; r8 = len
76 |
77 | mov rax, rcx
78 |
79 | crchw_loop:
80 | cmp r8, 8
81 | jl crchw_stragglers
82 |
83 | crc32 rax, qword ptr [rdx]
84 |
85 | add rdx, 8
86 | sub r8, 8
87 | jmp crchw_loop
88 |
89 | crchw_stragglers:
90 | cmp r8, 4
91 | jl crchw_stragglers2
92 |
93 | crc32 eax, dword ptr [rdx]
94 |
95 | add rdx, 4
96 | sub r8, 4
97 |
98 | crchw_stragglers2:
99 | cmp r8, 2
100 | jl crchw_stragglers3
101 |
102 | crc32 eax, word ptr [rdx]
103 |
104 | add rdx, 2
105 | sub r8, 2
106 |
107 | crchw_stragglers3:
108 | test r8, r8
109 | jz crchw_end
110 |
111 | crc32 eax, byte ptr [rdx]
112 | inc rdx
113 | dec r8
114 | jmp crchw_stragglers3
115 |
116 | crchw_end:
117 | ret
118 |
119 | ELSE
120 |
121 | EXTERN crctable:ABS
122 |
123 | ; uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
124 |
125 | PUBLIC calc_crc32c_sw@12
126 |
127 | calc_crc32c_sw@12:
128 |
129 | push ebp
130 | mov ebp, esp
131 |
132 | push esi
133 | push ebx
134 |
135 | mov eax, [ebp+8]
136 | mov edx, [ebp+12]
137 | mov ebx, [ebp+16]
138 |
139 | ; eax = crc / seed
140 | ; ebx = len
141 | ; esi = tmp
142 | ; edx = buf
143 | ; ecx = tmp2
144 |
145 | crcloop:
146 | test ebx, ebx
147 | jz crcend
148 |
149 | mov esi, eax
150 | shr esi, 8
151 | mov cl, byte ptr [edx]
152 | xor al, cl
153 | and eax, 255
154 | shl eax, 2
155 | mov eax, [crctable + eax]
156 | xor eax, esi
157 |
158 | inc edx
159 | dec ebx
160 |
161 | jmp crcloop
162 |
163 | crcend:
164 | pop ebx
165 | pop esi
166 |
167 | pop ebp
168 |
169 | ret 12
170 |
171 | ; ****************************************************
172 |
173 | ; uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
174 |
175 | PUBLIC calc_crc32c_hw@12
176 |
177 | calc_crc32c_hw@12:
178 |
179 | push ebp
180 | mov ebp, esp
181 |
182 | mov eax, [ebp+8]
183 | mov edx, [ebp+12]
184 | mov ecx, [ebp+16]
185 |
186 | ; eax = crc / seed
187 | ; ecx = len
188 | ; edx = buf
189 |
190 | crchw_loop:
191 | cmp ecx, 4
192 | jl crchw_stragglers
193 |
194 | crc32 eax, dword ptr [edx]
195 |
196 | add edx, 4
197 | sub ecx, 4
198 | jmp crchw_loop
199 |
200 | crchw_stragglers:
201 | cmp ecx, 2
202 | jl crchw_stragglers2
203 |
204 | crc32 eax, word ptr [edx]
205 |
206 | add edx, 2
207 | sub ecx, 2
208 |
209 | crchw_stragglers2:
210 | test ecx, ecx
211 | jz crchw_end
212 |
213 | crc32 eax, byte ptr [edx]
214 | inc edx
215 | dec ecx
216 | jmp crchw_stragglers2
217 |
218 | crchw_end:
219 | pop ebp
220 |
221 | ret 12
222 |
223 | ENDIF
224 |
225 | _TEXT ENDS
226 |
227 | end
228 |
--------------------------------------------------------------------------------
/src/crc32c.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "crc32c.h"
19 | #include
20 | #include
21 | #include
22 |
23 | crc_func calc_crc32c = calc_crc32c_sw;
24 |
25 | const uint32_t crctable[] = {
26 | 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
27 | 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
28 | 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
29 | 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
30 | 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
31 | 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
32 | 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
33 | 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
34 | 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
35 | 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
36 | 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
37 | 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
38 | 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
39 | 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
40 | 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
41 | 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
42 | 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
43 | 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
44 | 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
45 | 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
46 | 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
47 | 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
48 | 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
49 | 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
50 | 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
51 | 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
52 | 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
53 | 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
54 | 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
55 | 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
56 | 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
57 | 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
58 | };
59 |
60 | // x86 and amd64 versions live in asm files
61 | #if !defined(_X86_) && !defined(_AMD64_)
62 | uint32_t __stdcall calc_crc32c_sw(_In_ uint32_t seed, _In_reads_bytes_(msglen) uint8_t* msg, _In_ uint32_t msglen) {
63 | uint32_t rem = seed;
64 |
65 | for (uint32_t i = 0; i < msglen; i++) {
66 | rem = crctable[(rem ^ msg[i]) & 0xff] ^ (rem >> 8);
67 | }
68 |
69 | return rem;
70 | }
71 | #endif
72 |
--------------------------------------------------------------------------------
/src/crc32c.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #ifdef __cplusplus
6 | extern "C" {
7 | #endif
8 |
9 | #if defined(_X86_) || defined(_AMD64_) || defined(_ARM64_)
10 | uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
11 | #endif
12 |
13 | uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
14 |
15 | typedef uint32_t (__stdcall *crc_func)(uint32_t seed, uint8_t* msg, uint32_t msglen);
16 |
17 | extern crc_func calc_crc32c;
18 |
19 | #ifdef __cplusplus
20 | }
21 | #endif
22 |
--------------------------------------------------------------------------------
/src/fsrtl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * PROJECT: ReactOS Kernel - Vista+ APIs
3 | * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 | * FILE: lib/drivers/ntoskrnl_vista/fsrtl.c
5 | * PURPOSE: FsRtl functions of Vista+
6 | * PROGRAMMERS: Pierre Schweitzer
7 | */
8 |
9 | #include
10 | #include
11 |
12 | FORCEINLINE
13 | BOOLEAN
14 | IsNullGuid(IN PGUID Guid)
15 | {
16 | if (Guid->Data1 == 0 && Guid->Data2 == 0 && Guid->Data3 == 0 &&
17 | ((ULONG *)Guid->Data4)[0] == 0 && ((ULONG *)Guid->Data4)[1] == 0)
18 | {
19 | return TRUE;
20 | }
21 |
22 | return FALSE;
23 | }
24 |
25 | FORCEINLINE
26 | BOOLEAN
27 | IsEven(IN USHORT Digit)
28 | {
29 | return ((Digit & 1) != 1);
30 | }
31 |
32 | NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer)
33 | {
34 | USHORT DataLength;
35 | ULONG ReparseTag;
36 | PREPARSE_GUID_DATA_BUFFER GuidBuffer;
37 |
38 | /* Validate data size range */
39 | if (BufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE || BufferLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
40 | {
41 | return STATUS_IO_REPARSE_DATA_INVALID;
42 | }
43 |
44 | GuidBuffer = (PREPARSE_GUID_DATA_BUFFER)ReparseBuffer;
45 | DataLength = ReparseBuffer->ReparseDataLength;
46 | ReparseTag = ReparseBuffer->ReparseTag;
47 |
48 | /* Validate size consistency */
49 | if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE != BufferLength && DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE != BufferLength)
50 | {
51 | return STATUS_IO_REPARSE_DATA_INVALID;
52 | }
53 |
54 | /* REPARSE_DATA_BUFFER is reserved for MS tags */
55 | if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE == BufferLength && !IsReparseTagMicrosoft(ReparseTag))
56 | {
57 | return STATUS_IO_REPARSE_DATA_INVALID;
58 | }
59 |
60 | /* If that a GUID data buffer, its GUID cannot be null, and it cannot contain a MS tag */
61 | if (DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE == BufferLength && ((!IsReparseTagMicrosoft(ReparseTag)
62 | && IsNullGuid(&GuidBuffer->ReparseGuid)) || (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT || ReparseTag == IO_REPARSE_TAG_SYMLINK)))
63 | {
64 | return STATUS_IO_REPARSE_DATA_INVALID;
65 | }
66 |
67 | /* Check the data for MS non reserved tags */
68 | if (!(ReparseTag & 0xFFF0000) && ReparseTag != IO_REPARSE_TAG_RESERVED_ZERO && ReparseTag != IO_REPARSE_TAG_RESERVED_ONE)
69 | {
70 | /* If that's a mount point, validate the MountPointReparseBuffer branch */
71 | if (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
72 | {
73 | /* We need information */
74 | if (DataLength >= REPARSE_DATA_BUFFER_HEADER_SIZE)
75 | {
76 | /* Substitue must be the first in row */
77 | if (!ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset)
78 | {
79 | /* Substitude must be null-terminated */
80 | if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset == ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL))
81 | {
82 | /* There must just be the Offset/Length fields + buffer + 2 null chars */
83 | if (DataLength == ReparseBuffer->MountPointReparseBuffer.PrintNameLength + ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.SubstituteNameOffset)) + 2 * sizeof(UNICODE_NULL))
84 | {
85 | return STATUS_SUCCESS;
86 | }
87 | }
88 | }
89 | }
90 | }
91 | else
92 | {
93 | #define FIELDS_SIZE (FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
94 |
95 | /* If that's not a symlink, accept the MS tag as it */
96 | if (ReparseTag != IO_REPARSE_TAG_SYMLINK)
97 | {
98 | return STATUS_SUCCESS;
99 | }
100 |
101 | /* We need information */
102 | if (DataLength >= FIELDS_SIZE)
103 | {
104 | /* Validate lengths */
105 | if (ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength && ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength)
106 | {
107 | /* Validate unicode strings */
108 | if (IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength) &&
109 | IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset))
110 | {
111 | if ((DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE)
112 | && (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE))
113 | {
114 | return STATUS_SUCCESS;
115 | }
116 | }
117 | }
118 | }
119 | #undef FIELDS_SIZE
120 | }
121 |
122 | return STATUS_IO_REPARSE_DATA_INVALID;
123 | }
124 |
125 | return STATUS_IO_REPARSE_TAG_INVALID;
126 | }
127 |
--------------------------------------------------------------------------------
/src/galois.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "btrfs_drv.h"
19 |
20 | static const uint8_t glog[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
21 | 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
22 | 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
23 | 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
24 | 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
25 | 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
26 | 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
27 | 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
28 | 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
29 | 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
30 | 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
31 | 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
32 | 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
33 | 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
34 | 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
35 | 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01};
36 |
37 | static const uint8_t gilog[] = {0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
38 | 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
39 | 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
40 | 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
41 | 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
42 | 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
43 | 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
44 | 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
45 | 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
46 | 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
47 | 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
48 | 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
49 | 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
50 | 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
51 | 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
52 | 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf};
53 |
54 | // divides the bytes in data by 2^div
55 | void galois_divpower(uint8_t* data, uint8_t div, uint32_t len) {
56 | while (len > 0) {
57 | if (data[0] != 0) {
58 | if (gilog[data[0]] <= div)
59 | data[0] = glog[(gilog[data[0]] + (255 - div)) % 255];
60 | else
61 | data[0] = glog[(gilog[data[0]] - div) % 255];
62 | }
63 |
64 | data++;
65 | len--;
66 | }
67 | }
68 |
69 | uint8_t gpow2(uint8_t e) {
70 | return glog[e%255];
71 | }
72 |
73 | uint8_t gmul(uint8_t a, uint8_t b) {
74 | if (a == 0 || b == 0)
75 | return 0;
76 | else
77 | return glog[(gilog[a] + gilog[b]) % 255];
78 | }
79 |
80 | uint8_t gdiv(uint8_t a, uint8_t b) {
81 | if (b == 0) {
82 | return 0xff; // shouldn't happen
83 | } else if (a == 0) {
84 | return 0;
85 | } else {
86 | if (gilog[a] >= gilog[b])
87 | return glog[(gilog[a] - gilog[b]) % 255];
88 | else
89 | return glog[255-((gilog[b] - gilog[a]) % 255)];
90 | }
91 | }
92 |
93 | // The code from the following functions is derived from the paper
94 | // "The mathematics of RAID-6", by H. Peter Anvin.
95 | // https://www.kernel.org/pub/linux/kernel/people/hpa/raid6.pdf
96 |
97 | #if defined(_AMD64_) || defined(_ARM64_)
98 | __inline static uint64_t galois_double_mask64(uint64_t v) {
99 | v &= 0x8080808080808080;
100 | return (v << 1) - (v >> 7);
101 | }
102 | #else
103 | __inline static uint32_t galois_double_mask32(uint32_t v) {
104 | v &= 0x80808080;
105 | return (v << 1) - (v >> 7);
106 | }
107 | #endif
108 |
109 | void galois_double(uint8_t* data, uint32_t len) {
110 | // FIXME - SIMD?
111 |
112 | #if defined(_AMD64_) || defined(_ARM64_)
113 | while (len > sizeof(uint64_t)) {
114 | uint64_t v = *((uint64_t*)data), vv;
115 |
116 | vv = (v << 1) & 0xfefefefefefefefe;
117 | vv ^= galois_double_mask64(v) & 0x1d1d1d1d1d1d1d1d;
118 | *((uint64_t*)data) = vv;
119 |
120 | data += sizeof(uint64_t);
121 | len -= sizeof(uint64_t);
122 | }
123 | #else
124 | while (len > sizeof(uint32_t)) {
125 | uint32_t v = *((uint32_t*)data), vv;
126 |
127 | vv = (v << 1) & 0xfefefefe;
128 | vv ^= galois_double_mask32(v) & 0x1d1d1d1d;
129 | *((uint32_t*)data) = vv;
130 |
131 | data += sizeof(uint32_t);
132 | len -= sizeof(uint32_t);
133 | }
134 | #endif
135 |
136 | while (len > 0) {
137 | data[0] = (data[0] << 1) ^ ((data[0] & 0x80) ? 0x1d : 0);
138 | data++;
139 | len--;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/mkbtrfs/mkbtrfs.rc.in:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "@CMAKE_CURRENT_SOURCE_DIR@/src/mkbtrfs/resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (United Kingdom) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Version
51 | //
52 |
53 | VS_VERSION_INFO VERSIONINFO
54 | FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
55 | PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
56 | FILEFLAGSMASK 0x17L
57 | #ifdef _DEBUG
58 | FILEFLAGS 0x1L
59 | #else
60 | FILEFLAGS 0x0L
61 | #endif
62 | FILEOS 0x4L
63 | FILETYPE 0x0L
64 | FILESUBTYPE 0x0L
65 | BEGIN
66 | BLOCK "StringFileInfo"
67 | BEGIN
68 | BLOCK "080904b0"
69 | BEGIN
70 | VALUE "FileDescription", "Btrfs formatting utility"
71 | VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
72 | VALUE "InternalName", "mkbtrfs"
73 | VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-24"
74 | VALUE "OriginalFilename", "mkbtrfs.exe"
75 | VALUE "ProductName", "WinBtrfs"
76 | VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
77 | END
78 | END
79 | BLOCK "VarFileInfo"
80 | BEGIN
81 | VALUE "Translation", 0x809, 1200
82 | END
83 | END
84 |
85 |
86 | /////////////////////////////////////////////////////////////////////////////
87 | //
88 | // String Table
89 | //
90 |
91 | STRINGTABLE
92 | BEGIN
93 | IDS_USAGE "Usage: %s device [label]\n"
94 | IDS_MULTIBYTE_FAILED "MultiByteToWideChar failed (error %lu)"
95 | IDS_CANT_RECOGNIZE_DRIVE "Could not recognize drive %s"
96 | IDS_CANT_LOAD_DLL "Unable to load %s"
97 | IDS_CANT_FIND_FORMATEX "Could not load function FormatEx in %s"
98 | IDS_FORMATEX_ERROR "FormatEx failed"
99 | IDS_SUCCESS "Completed successfully."
100 | IDS_CANT_FIND_SETSIZES "Could not load function SetSizes in %s"
101 | IDS_TOO_MANY_ARGS "Too many arguments."
102 | IDS_UNKNOWN_ARG "Unknown argument."
103 | IDS_NO_SECTOR_SIZE "No sector size specified."
104 | END
105 |
106 | STRINGTABLE
107 | BEGIN
108 | IDS_NO_NODE_SIZE "No node size specified."
109 | IDS_CANT_FIND_FUNCTION "Could not load function %s in %s"
110 | IDS_USAGE2 "The device parameter can either be a drive letter, e.g. D:, or a device path,\nsuch as \\Device\\Harddisk0\\Partition2.\n\nTo format the whole of the first hard disk without using partitions, you would\nneed to use the parameter \\Device\\Harddisk0\\Partition0.\n\nSupported flags:\n\n/sectorsize:num Sets the sector size. This must be a\n multiple of the size that the disk itself\n reports. The default is 4096, which should\n be used unless you have a good reason.\n\n/nodesize:num Sets the node size, i.e. the size of the\n metadata trees. The default is 16384. This\n needs to either be the same as sector size,\n or a power of two multiple.\n \n/csum:id Sets the checksum algorithm to use. Valid\n values are crc32c, xxhash, sha256, and\n blake2.\n\n/mixed Enables or disables mixed block groups,\n/notmixed which store data and and metadata in the\n same chunks. The default is disabled. This\n is only useful for very small filesystems.\n\n/extiref Enables or disables extended inode refs,\n/notextiref which increase the number of hardlinks\n allowed. The default is enabled.\n\n/skinnymetadata Enables or disable skinny metadata, which\n/notskinnymetadata allows more efficient storage of metadata\n refs. The default is enabled.\n\n/noholes Enables or disables whether sparse extents\n/notnoholes should be stored implicitly, which can save\n a little space. The default is enabled.\n\n/freespacetree Enables or disables storing the free-space\n/notfreespacetree cache in a tree rather than a blob.\n Supported from Linux 4.5. The default is\n enabled.\n\n/blockgrouptree Enables or disables the block group tree,\n/notblockgrouptree which can decrease mount times. Supported\n from Linux 6.1. The default is disabled.\n Implies /noholes and /freespacetree."
111 | IDS_NO_CSUM "No csum value given. Valid values are crc32c, xxhash, sha256, and blake2."
112 | IDS_INVALID_CSUM_TYPE "Invalid csum value. Valid values are crc32c, xxhash, sha256, and blake2."
113 | END
114 |
115 | #endif // English (United Kingdom) resources
116 | /////////////////////////////////////////////////////////////////////////////
117 |
118 |
119 |
120 | #ifndef APSTUDIO_INVOKED
121 | /////////////////////////////////////////////////////////////////////////////
122 | //
123 | // Generated from the TEXTINCLUDE 3 resource.
124 | //
125 |
126 |
127 | /////////////////////////////////////////////////////////////////////////////
128 | #endif // not APSTUDIO_INVOKED
129 |
130 |
--------------------------------------------------------------------------------
/src/mkbtrfs/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by mkbtrfs.rc
4 | //
5 | #define IDS_USAGE 101
6 | #define IDS_MULTIBYTE_FAILED 102
7 | #define IDS_CANT_RECOGNIZE_DRIVE 103
8 | #define IDS_CANT_LOAD_DLL 104
9 | #define IDS_CANT_FIND_FORMATEX 105
10 | #define IDS_FORMATEX_ERROR 106
11 | #define IDS_SUCCESS 107
12 | #define IDS_CANT_FIND_SETSIZES 108
13 | #define IDS_TOO_MANY_ARGS 109
14 | #define IDS_UNKNOWN_ARG 110
15 | #define IDS_NO_SECTOR_SIZE 111
16 | #define IDS_NO_NODE_SIZE 112
17 | #define IDS_CANT_FIND_FUNCTION 113
18 | #define IDS_USAGE2 114
19 | #define IDS_NO_CSUM 115
20 | #define IDS_INVALID_CSUM_TYPE 116
21 |
22 | // Next default values for new objects
23 | //
24 | #ifdef APSTUDIO_INVOKED
25 | #ifndef APSTUDIO_READONLY_SYMBOLS
26 | #define _APS_NEXT_RESOURCE_VALUE 102
27 | #define _APS_NEXT_COMMAND_VALUE 40001
28 | #define _APS_NEXT_CONTROL_VALUE 1001
29 | #define _APS_NEXT_SYMED_VALUE 101
30 | #endif
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by btrfs.rc
4 | //
5 |
6 | // Next default values for new objects
7 | //
8 | #ifdef APSTUDIO_INVOKED
9 | #ifndef APSTUDIO_READONLY_SYMBOLS
10 | #define _APS_NEXT_RESOURCE_VALUE 101
11 | #define _APS_NEXT_COMMAND_VALUE 40001
12 | #define _APS_NEXT_CONTROL_VALUE 1001
13 | #define _APS_NEXT_SYMED_VALUE 101
14 | #endif
15 | #endif
16 |
--------------------------------------------------------------------------------
/src/sha256.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | // Public domain code from https://github.com/amosnier/sha-2
5 |
6 | // FIXME - x86 SHA extensions
7 |
8 | #define CHUNK_SIZE 64
9 | #define TOTAL_LEN_LEN 8
10 |
11 | /*
12 | * ABOUT bool: this file does not use bool in order to be as pre-C99 compatible as possible.
13 | */
14 |
15 | /*
16 | * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here.
17 | * When useful for clarification, portions of the pseudo-code are reproduced here too.
18 | */
19 |
20 | /*
21 | * Initialize array of round constants:
22 | * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
23 | */
24 | static const uint32_t k[] = {
25 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
26 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
27 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
28 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
29 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
30 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
31 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
32 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
33 | };
34 |
35 | struct buffer_state {
36 | const uint8_t * p;
37 | size_t len;
38 | size_t total_len;
39 | int single_one_delivered; /* bool */
40 | int total_len_delivered; /* bool */
41 | };
42 |
43 | static inline uint32_t right_rot(uint32_t value, unsigned int count)
44 | {
45 | /*
46 | * Defined behaviour in standard C for all count where 0 < count < 32,
47 | * which is what we need here.
48 | */
49 | return value >> count | value << (32 - count);
50 | }
51 |
52 | static void init_buf_state(struct buffer_state * state, const void * input, size_t len)
53 | {
54 | state->p = input;
55 | state->len = len;
56 | state->total_len = len;
57 | state->single_one_delivered = 0;
58 | state->total_len_delivered = 0;
59 | }
60 |
61 | /* Return value: bool */
62 | static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
63 | {
64 | size_t space_in_chunk;
65 |
66 | if (state->total_len_delivered) {
67 | return 0;
68 | }
69 |
70 | if (state->len >= CHUNK_SIZE) {
71 | memcpy(chunk, state->p, CHUNK_SIZE);
72 | state->p += CHUNK_SIZE;
73 | state->len -= CHUNK_SIZE;
74 | return 1;
75 | }
76 |
77 | memcpy(chunk, state->p, state->len);
78 | chunk += state->len;
79 | space_in_chunk = CHUNK_SIZE - state->len;
80 | state->p += state->len;
81 | state->len = 0;
82 |
83 | /* If we are here, space_in_chunk is one at minimum. */
84 | if (!state->single_one_delivered) {
85 | *chunk++ = 0x80;
86 | space_in_chunk -= 1;
87 | state->single_one_delivered = 1;
88 | }
89 |
90 | /*
91 | * Now:
92 | * - either there is enough space left for the total length, and we can conclude,
93 | * - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
94 | * In the latter case, we will conclude at the next invokation of this function.
95 | */
96 | if (space_in_chunk >= TOTAL_LEN_LEN) {
97 | const size_t left = space_in_chunk - TOTAL_LEN_LEN;
98 | size_t len = state->total_len;
99 | int i;
100 | memset(chunk, 0x00, left);
101 | chunk += left;
102 |
103 | /* Storing of len * 8 as a big endian 64-bit without overflow. */
104 | chunk[7] = (uint8_t) (len << 3);
105 | len >>= 5;
106 | for (i = 6; i >= 0; i--) {
107 | chunk[i] = (uint8_t) len;
108 | len >>= 8;
109 | }
110 | state->total_len_delivered = 1;
111 | } else {
112 | memset(chunk, 0x00, space_in_chunk);
113 | }
114 |
115 | return 1;
116 | }
117 |
118 | /*
119 | * Limitations:
120 | * - Since input is a pointer in RAM, the data to hash should be in RAM, which could be a problem
121 | * for large data sizes.
122 | * - SHA algorithms theoretically operate on bit strings. However, this implementation has no support
123 | * for bit string lengths that are not multiples of eight, and it really operates on arrays of bytes.
124 | * In particular, the len parameter is a number of bytes.
125 | */
126 | void calc_sha256(uint8_t* hash, const void* input, size_t len)
127 | {
128 | /*
129 | * Note 1: All integers (expect indexes) are 32-bit unsigned integers and addition is calculated modulo 2^32.
130 | * Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 = i = 63
131 | * Note 3: The compression function uses 8 working variables, a through h
132 | * Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
133 | * and when parsing message block data from bytes to words, for example,
134 | * the first word of the input message "abc" after padding is 0x61626380
135 | */
136 |
137 | /*
138 | * Initialize hash values:
139 | * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
140 | */
141 | uint32_t h[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
142 | unsigned i, j;
143 |
144 | /* 512-bit chunks is what we will operate on. */
145 | uint8_t chunk[64];
146 |
147 | struct buffer_state state;
148 |
149 | init_buf_state(&state, input, len);
150 |
151 | while (calc_chunk(chunk, &state)) {
152 | uint32_t ah[8];
153 |
154 | const uint8_t *p = chunk;
155 |
156 | /* Initialize working variables to current hash value: */
157 | for (i = 0; i < 8; i++)
158 | ah[i] = h[i];
159 |
160 | /* Compression function main loop: */
161 | for (i = 0; i < 4; i++) {
162 | /*
163 | * The w-array is really w[64], but since we only need
164 | * 16 of them at a time, we save stack by calculating
165 | * 16 at a time.
166 | *
167 | * This optimization was not there initially and the
168 | * rest of the comments about w[64] are kept in their
169 | * initial state.
170 | */
171 |
172 | /*
173 | * create a 64-entry message schedule array w[0..63] of 32-bit words
174 | * (The initial values in w[0..63] don't matter, so many implementations zero them here)
175 | * copy chunk into first 16 words w[0..15] of the message schedule array
176 | */
177 | uint32_t w[16];
178 |
179 | for (j = 0; j < 16; j++) {
180 | if (i == 0) {
181 | w[j] = (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 |
182 | (uint32_t) p[2] << 8 | (uint32_t) p[3];
183 | p += 4;
184 | } else {
185 | /* Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: */
186 | const uint32_t s0 = right_rot(w[(j + 1) & 0xf], 7) ^ right_rot(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3);
187 | const uint32_t s1 = right_rot(w[(j + 14) & 0xf], 17) ^ right_rot(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10);
188 | w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1;
189 | }
190 | const uint32_t s1 = right_rot(ah[4], 6) ^ right_rot(ah[4], 11) ^ right_rot(ah[4], 25);
191 | const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]);
192 | const uint32_t temp1 = ah[7] + s1 + ch + k[i << 4 | j] + w[j];
193 | const uint32_t s0 = right_rot(ah[0], 2) ^ right_rot(ah[0], 13) ^ right_rot(ah[0], 22);
194 | const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]);
195 | const uint32_t temp2 = s0 + maj;
196 |
197 | ah[7] = ah[6];
198 | ah[6] = ah[5];
199 | ah[5] = ah[4];
200 | ah[4] = ah[3] + temp1;
201 | ah[3] = ah[2];
202 | ah[2] = ah[1];
203 | ah[1] = ah[0];
204 | ah[0] = temp1 + temp2;
205 | }
206 | }
207 |
208 | /* Add the compressed chunk to the current hash value: */
209 | for (i = 0; i < 8; i++)
210 | h[i] += ah[i];
211 | }
212 |
213 | /* Produce the final hash value (big-endian): */
214 | for (i = 0, j = 0; i < 8; i++)
215 | {
216 | hash[j++] = (uint8_t) (h[i] >> 24);
217 | hash[j++] = (uint8_t) (h[i] >> 16);
218 | hash[j++] = (uint8_t) (h[i] >> 8);
219 | hash[j++] = (uint8_t) h[i];
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/src/shellext/balance.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include "../btrfsioctl.h"
22 |
23 | class BtrfsBalance {
24 | public:
25 | BtrfsBalance(const wstring& drive, bool RemoveDevice = false, bool ShrinkDevice = false) {
26 | removing = false;
27 | devices = nullptr;
28 | called_from_RemoveDevice = RemoveDevice;
29 | called_from_ShrinkDevice = ShrinkDevice;
30 | fn = drive;
31 | }
32 |
33 | void ShowBalance(HWND hwndDlg);
34 | INT_PTR CALLBACK BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
35 | INT_PTR CALLBACK BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
36 |
37 | private:
38 | void ShowBalanceOptions(HWND hwndDlg, uint8_t type);
39 | void SaveBalanceOpts(HWND hwndDlg);
40 | void StartBalance(HWND hwndDlg);
41 | void RefreshBalanceDlg(HWND hwndDlg, bool first);
42 | void PauseBalance(HWND hwndDlg);
43 | void StopBalance(HWND hwndDlg);
44 |
45 | uint32_t balance_status;
46 | btrfs_balance_opts data_opts, metadata_opts, system_opts;
47 | uint8_t opts_type;
48 | btrfs_query_balance bqb;
49 | bool cancelling;
50 | bool removing;
51 | bool shrinking;
52 | wstring fn;
53 | btrfs_device* devices;
54 | bool readonly;
55 | bool called_from_RemoveDevice, called_from_ShrinkDevice;
56 | };
57 |
--------------------------------------------------------------------------------
/src/shellext/contextmenu.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 |
22 | extern LONG objs_loaded;
23 |
24 | class BtrfsContextMenu : public IShellExtInit, IContextMenu {
25 | public:
26 | BtrfsContextMenu() {
27 | refcount = 0;
28 | ignore = true;
29 | stgm_set = false;
30 | uacicon = nullptr;
31 | allow_snapshot = false;
32 | InterlockedIncrement(&objs_loaded);
33 | }
34 |
35 | virtual ~BtrfsContextMenu() {
36 | if (stgm_set)
37 | ReleaseStgMedium(&stgm);
38 |
39 | if (uacicon)
40 | DeleteObject(uacicon);
41 |
42 | InterlockedDecrement(&objs_loaded);
43 | }
44 |
45 | // IUnknown
46 |
47 | HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
48 |
49 | ULONG __stdcall AddRef() {
50 | return InterlockedIncrement(&refcount);
51 | }
52 |
53 | ULONG __stdcall Release() {
54 | LONG rc = InterlockedDecrement(&refcount);
55 |
56 | if (rc == 0)
57 | delete this;
58 |
59 | return rc;
60 | }
61 |
62 | // IShellExtInit
63 |
64 | virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) override;
65 |
66 | // IContextMenu
67 |
68 | virtual HRESULT __stdcall QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override;
69 | virtual HRESULT __stdcall InvokeCommand(LPCMINVOKECOMMANDINFO pici) override;
70 | virtual HRESULT __stdcall GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax) override;
71 |
72 | private:
73 | LONG refcount;
74 | bool ignore, allow_snapshot;
75 | bool bg;
76 | wstring path;
77 | STGMEDIUM stgm;
78 | bool stgm_set;
79 | HBITMAP uacicon;
80 |
81 | void reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir);
82 | void get_uac_icon();
83 | };
84 |
--------------------------------------------------------------------------------
/src/shellext/devices.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include
22 | #include
23 | #include "../btrfsioctl.h"
24 |
25 | typedef struct {
26 | wstring pnp_name;
27 | wstring friendly_name;
28 | wstring drive;
29 | wstring fstype;
30 | ULONG disk_num;
31 | ULONG part_num;
32 | uint64_t size;
33 | bool has_parts;
34 | BTRFS_UUID fs_uuid;
35 | BTRFS_UUID dev_uuid;
36 | bool ignore;
37 | bool multi_device;
38 | bool is_disk;
39 | } device;
40 |
41 | typedef struct {
42 | const WCHAR* name;
43 | const char* magic;
44 | ULONG magiclen;
45 | uint32_t sboff;
46 | uint32_t kboff;
47 | } fs_identifier;
48 |
49 | // This list is compiled from information in libblkid, part of util-linux
50 | // and likewise under the LGPL. Thanks!
51 |
52 | const static fs_identifier fs_ident[] = {
53 | { L"BeFS", "BFS1", 4, 0x20, 0 },
54 | { L"BeFS", "1SFB", 4, 0x20, 0 },
55 | { L"BeFS", "BFS1", 4, 0x220, 0 },
56 | { L"BeFS", "1SFB", 4, 0x220, 0 },
57 | { L"BFS", "\xce\xfa\xad\x1b", 4, 0, 0 },
58 | { L"RomFS", "-rom1fs-", 8, 0, 0 },
59 | { L"SquashFS", "hsqs", 4, 0, 0 },
60 | { L"SquashFS", "sqsh", 4, 0, 0 },
61 | { L"SquashFS", "hsqs", 4, 0, 0 },
62 | { L"UBIFS", "\x31\x18\x10\x06", 4, 0, 0 },
63 | { L"XFS", "XFSB", 4, 0, 0 },
64 | { L"ext2", "\123\357", 2, 0x38, 1 },
65 | { L"F2FS", "\x10\x20\xF5\xF2", 4, 0, 1 },
66 | { L"HFS", "BD", 2, 0, 1 },
67 | { L"HFS", "BD", 2, 0, 1 },
68 | { L"HFS", "H+", 2, 0, 1 },
69 | { L"HFS", "HX", 2, 0, 1 },
70 | { L"Minix", "\177\023", 2, 0x10, 1 },
71 | { L"Minix", "\217\023", 2, 0x10, 1 },
72 | { L"Minix", "\023\177", 2, 0x10, 1 },
73 | { L"Minix", "\023\217", 2, 0x10, 1 },
74 | { L"Minix", "\150\044", 2, 0x10, 1 },
75 | { L"Minix", "\170\044", 2, 0x10, 1 },
76 | { L"Minix", "\044\150", 2, 0x10, 1 },
77 | { L"Minix", "\044\170", 2, 0x10, 1 },
78 | { L"Minix", "\132\115", 2, 0x10, 1 },
79 | { L"Minix", "\115\132", 2, 0x10, 1 },
80 | { L"OCFS", "OCFSV2", 6, 0, 1 },
81 | { L"SysV", "\x2b\x55\x44", 3, 0x400, 1 },
82 | { L"SysV", "\x44\x55\x2b", 3, 0x400, 1 },
83 | { L"VXFS", "\365\374\001\245", 4, 0, 1 },
84 | { L"OCFS", "OCFSV2", 6, 0, 2 },
85 | { L"ExFAT", "EXFAT ", 8, 3, 0 },
86 | { L"NTFS", "NTFS ", 8, 3, 0 },
87 | { L"NetWare", "SPB5", 4, 0, 4 },
88 | { L"OCFS", "OCFSV2", 6, 0, 4 },
89 | { L"HPFS", "\x49\xe8\x95\xf9", 4, 0, 8 },
90 | { L"OCFS", "OracleCFS", 9, 0, 8 },
91 | { L"OCFS", "OCFSV2", 6, 0, 8 },
92 | { L"ReFS", "\000\000\000ReFS\000", 8, 0, 0 },
93 | { L"ReiserFS", "ReIsErFs", 8, 0x34, 8 },
94 | { L"ReiserFS", "ReIsErFs", 8, 20, 8 },
95 | { L"ISO9660", "CD001", 5, 1, 32 },
96 | { L"ISO9660", "CDROM", 5, 9, 32 },
97 | { L"JFS", "JFS1", 4, 0, 32 },
98 | { L"OCFS", "ORCLDISK", 8, 32, 0 },
99 | { L"UDF", "BEA01", 5, 1, 32 },
100 | { L"UDF", "BOOT2", 5, 1, 32 },
101 | { L"UDF", "CD001", 5, 1, 32 },
102 | { L"UDF", "CDW02", 5, 1, 32 },
103 | { L"UDF", "NSR02", 5, 1, 32 },
104 | { L"UDF", "NSR03", 5, 1, 32 },
105 | { L"UDF", "TEA01", 5, 1, 32 },
106 | { L"Btrfs", "_BHRfS_M", 8, 0x40, 64 },
107 | { L"GFS", "\x01\x16\x19\x70", 4, 0, 64 },
108 | { L"GFS", "\x01\x16\x19\x70", 4, 0, 64 },
109 | { L"ReiserFS", "ReIsEr2Fs", 9, 0x34, 64 },
110 | { L"ReiserFS", "ReIsEr3Fs", 9, 0x34, 64 },
111 | { L"ReiserFS", "ReIsErFs", 8, 0x34, 64 },
112 | { L"ReiserFS", "ReIsEr4", 7, 0, 64 },
113 | { L"VMFS", "\x0d\xd0\x01\xc0", 4, 0, 1024 },
114 | { L"VMFS", "\x5e\xf1\xab\x2f", 4, 0, 2048 },
115 | { L"FAT", "MSWIN", 5, 0x52, 0 },
116 | { L"FAT", "FAT32 ", 8, 0x52, 0 },
117 | { L"FAT", "MSDOS", 5, 0x36, 0 },
118 | { L"FAT", "FAT16 ", 8, 0x36, 0 },
119 | { L"FAT", "FAT12 ", 8, 0x36, 0 },
120 | { L"FAT", "FAT ", 8, 0x36, 0 },
121 | { L"FAT", "\353", 1, 0, 0 },
122 | { L"FAT", "\351", 1, 0, 0 },
123 | { L"FAT", "\125\252", 2, 0x1fe, 0 },
124 | { nullptr, nullptr, 0, 0, 0 }
125 | };
126 |
127 | class BtrfsDeviceAdd {
128 | public:
129 | INT_PTR CALLBACK DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
130 | void ShowDialog();
131 | void AddDevice(HWND hwndDlg);
132 | BtrfsDeviceAdd(HINSTANCE hinst, HWND hwnd, WCHAR* cmdline);
133 |
134 | private:
135 | void populate_device_tree(HWND tree);
136 |
137 | HINSTANCE hinst;
138 | HWND hwnd;
139 | WCHAR* cmdline;
140 | device* sel;
141 | vector device_list;
142 | };
143 |
144 | class BtrfsDeviceResize {
145 | public:
146 | INT_PTR CALLBACK DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
147 | void ShowDialog(HWND hwnd, const wstring& fn, uint64_t dev_id);
148 |
149 | private:
150 | void do_resize(HWND hwndDlg);
151 |
152 | uint64_t dev_id, new_size;
153 | wstring fn;
154 | WCHAR new_size_text[255];
155 | btrfs_device dev_info;
156 | };
157 |
--------------------------------------------------------------------------------
/src/shellext/factory.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "shellext.h"
19 | #include
20 | #include "factory.h"
21 | #include "iconoverlay.h"
22 | #include "contextmenu.h"
23 | #include "propsheet.h"
24 | #include "volpropsheet.h"
25 |
26 | HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
27 | if (iid == IID_IUnknown || iid == IID_IClassFactory) {
28 | *ppv = static_cast(this);
29 | } else {
30 | *ppv = nullptr;
31 | return E_NOINTERFACE;
32 | }
33 |
34 | reinterpret_cast(*ppv)->AddRef();
35 |
36 | return S_OK;
37 | }
38 |
39 | HRESULT __stdcall Factory::LockServer(BOOL) {
40 | return E_NOTIMPL;
41 | }
42 |
43 | HRESULT __stdcall Factory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
44 | if (pUnknownOuter)
45 | return CLASS_E_NOAGGREGATION;
46 |
47 | switch (type) {
48 | case FactoryIconHandler:
49 | if (iid == IID_IUnknown || iid == IID_IShellIconOverlayIdentifier) {
50 | BtrfsIconOverlay* bio = new BtrfsIconOverlay;
51 | if (!bio)
52 | return E_OUTOFMEMORY;
53 |
54 | return bio->QueryInterface(iid, ppv);
55 | }
56 | break;
57 |
58 | case FactoryContextMenu:
59 | if (iid == IID_IUnknown || iid == IID_IContextMenu || iid == IID_IShellExtInit) {
60 | BtrfsContextMenu* bcm = new BtrfsContextMenu;
61 | if (!bcm)
62 | return E_OUTOFMEMORY;
63 |
64 | return bcm->QueryInterface(iid, ppv);
65 | }
66 | break;
67 |
68 | case FactoryPropSheet:
69 | if (iid == IID_IUnknown || iid == IID_IShellPropSheetExt || iid == IID_IShellExtInit) {
70 | BtrfsPropSheet* bps = new BtrfsPropSheet;
71 | if (!bps)
72 | return E_OUTOFMEMORY;
73 |
74 | return bps->QueryInterface(iid, ppv);
75 | }
76 | break;
77 |
78 | case FactoryVolPropSheet:
79 | if (iid == IID_IUnknown || iid == IID_IShellPropSheetExt || iid == IID_IShellExtInit) {
80 | BtrfsVolPropSheet* bps = new BtrfsVolPropSheet;
81 | if (!bps)
82 | return E_OUTOFMEMORY;
83 |
84 | return bps->QueryInterface(iid, ppv);
85 | }
86 | break;
87 |
88 | default:
89 | break;
90 | }
91 |
92 | *ppv = nullptr;
93 | return E_NOINTERFACE;
94 | }
95 |
--------------------------------------------------------------------------------
/src/shellext/factory.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | extern LONG objs_loaded;
21 |
22 | typedef enum {
23 | FactoryUnknown,
24 | FactoryIconHandler,
25 | FactoryContextMenu,
26 | FactoryPropSheet,
27 | FactoryVolPropSheet
28 | } factory_type;
29 |
30 | class Factory : public IClassFactory {
31 | public:
32 | Factory() {
33 | refcount = 0;
34 | type = FactoryUnknown;
35 | InterlockedIncrement(&objs_loaded);
36 | }
37 |
38 | virtual ~Factory() {
39 | InterlockedDecrement(&objs_loaded);
40 | }
41 |
42 | // IUnknown
43 |
44 | HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
45 |
46 | ULONG __stdcall AddRef() {
47 | return InterlockedIncrement(&refcount);
48 | }
49 |
50 | ULONG __stdcall Release() {
51 | LONG rc = InterlockedDecrement(&refcount);
52 |
53 | if (rc == 0)
54 | delete this;
55 |
56 | return rc;
57 | }
58 |
59 | // IClassFactory
60 |
61 | virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) override;
62 | virtual HRESULT __stdcall LockServer(BOOL bLock) override;
63 |
64 | factory_type type;
65 |
66 | private:
67 | LONG refcount;
68 | };
69 |
--------------------------------------------------------------------------------
/src/shellext/iconoverlay.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "shellext.h"
19 | #include
20 | #include
21 | #include "iconoverlay.h"
22 | #include "../btrfsioctl.h"
23 |
24 | HRESULT __stdcall BtrfsIconOverlay::QueryInterface(REFIID riid, void **ppObj) {
25 | if (riid == IID_IUnknown || riid == IID_IShellIconOverlayIdentifier) {
26 | *ppObj = static_cast(this);
27 | AddRef();
28 | return S_OK;
29 | }
30 |
31 | *ppObj = nullptr;
32 | return E_NOINTERFACE;
33 | }
34 |
35 | HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) noexcept {
36 | if (GetModuleFileNameW(module, pwszIconFile, cchMax) == 0)
37 | return E_FAIL;
38 |
39 | if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
40 | return E_FAIL;
41 |
42 | if (!pIndex)
43 | return E_INVALIDARG;
44 |
45 | if (!pdwFlags)
46 | return E_INVALIDARG;
47 |
48 | *pIndex = 0;
49 | *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
50 |
51 | return S_OK;
52 | }
53 |
54 | HRESULT __stdcall BtrfsIconOverlay::GetPriority(int *pPriority) noexcept {
55 | if (!pPriority)
56 | return E_INVALIDARG;
57 |
58 | *pPriority = 0;
59 |
60 | return S_OK;
61 | }
62 |
63 | HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD) noexcept {
64 | win_handle h;
65 | NTSTATUS Status;
66 | IO_STATUS_BLOCK iosb;
67 | btrfs_get_file_ids bgfi;
68 |
69 | h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
70 |
71 | if (h == INVALID_HANDLE_VALUE)
72 | return S_FALSE;
73 |
74 | Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
75 |
76 | if (!NT_SUCCESS(Status))
77 | return S_FALSE;
78 |
79 | return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE;
80 | }
81 |
--------------------------------------------------------------------------------
/src/shellext/iconoverlay.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 |
22 | extern LONG objs_loaded;
23 |
24 | class BtrfsIconOverlay : public IShellIconOverlayIdentifier {
25 | public:
26 | BtrfsIconOverlay() {
27 | refcount = 0;
28 | InterlockedIncrement(&objs_loaded);
29 | }
30 |
31 | virtual ~BtrfsIconOverlay() {
32 | InterlockedDecrement(&objs_loaded);
33 | }
34 |
35 | // IUnknown
36 |
37 | HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
38 |
39 | ULONG __stdcall AddRef() {
40 | return InterlockedIncrement(&refcount);
41 | }
42 |
43 | ULONG __stdcall Release() {
44 | LONG rc = InterlockedDecrement(&refcount);
45 |
46 | if (rc == 0)
47 | delete this;
48 |
49 | return rc;
50 | }
51 |
52 | // IShellIconOverlayIdentifier
53 |
54 | virtual HRESULT __stdcall GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) noexcept override;
55 | virtual HRESULT __stdcall GetPriority(int *pPriority) noexcept override;
56 | virtual HRESULT __stdcall IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) noexcept override;
57 |
58 | private:
59 | LONG refcount;
60 | };
61 |
--------------------------------------------------------------------------------
/src/shellext/mountmgr.cpp:
--------------------------------------------------------------------------------
1 | #include "shellext.h"
2 | #include "mountmgr.h"
3 | #include
4 |
5 | using namespace std;
6 |
7 | mountmgr::mountmgr() {
8 | UNICODE_STRING us;
9 | OBJECT_ATTRIBUTES attr;
10 | IO_STATUS_BLOCK iosb;
11 | NTSTATUS Status;
12 |
13 | RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME);
14 | InitializeObjectAttributes(&attr, &us, 0, nullptr, nullptr);
15 |
16 | Status = NtOpenFile(&h, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
17 | FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
18 |
19 | if (!NT_SUCCESS(Status))
20 | throw ntstatus_error(Status);
21 | }
22 |
23 | mountmgr::~mountmgr() {
24 | NtClose(h);
25 | }
26 |
27 | void mountmgr::create_point(wstring_view symlink, wstring_view device) const {
28 | NTSTATUS Status;
29 | IO_STATUS_BLOCK iosb;
30 |
31 | vector buf(sizeof(MOUNTMGR_CREATE_POINT_INPUT) + ((symlink.length() + device.length()) * sizeof(WCHAR)));
32 | auto mcpi = reinterpret_cast(buf.data());
33 |
34 | mcpi->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
35 | mcpi->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
36 | mcpi->DeviceNameOffset = (USHORT)(mcpi->SymbolicLinkNameOffset + mcpi->SymbolicLinkNameLength);
37 | mcpi->DeviceNameLength = (USHORT)(device.length() * sizeof(WCHAR));
38 |
39 | memcpy((uint8_t*)mcpi + mcpi->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
40 | memcpy((uint8_t*)mcpi + mcpi->DeviceNameOffset, device.data(), device.length() * sizeof(WCHAR));
41 |
42 | Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_CREATE_POINT,
43 | buf.data(), (ULONG)buf.size(), nullptr, 0);
44 |
45 | if (!NT_SUCCESS(Status))
46 | throw ntstatus_error(Status);
47 | }
48 |
49 | void mountmgr::delete_points(wstring_view symlink, wstring_view unique_id, wstring_view device_name) const {
50 | NTSTATUS Status;
51 | IO_STATUS_BLOCK iosb;
52 |
53 | vector buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR)));
54 | auto mmp = reinterpret_cast(buf.data());
55 |
56 | memset(mmp, 0, sizeof(MOUNTMGR_MOUNT_POINT));
57 |
58 | if (symlink.length() > 0) {
59 | mmp->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
60 | mmp->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
61 | memcpy((uint8_t*)mmp + mmp->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
62 | }
63 |
64 | if (unique_id.length() > 0) {
65 | if (mmp->SymbolicLinkNameLength == 0)
66 | mmp->UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINT);
67 | else
68 | mmp->UniqueIdOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
69 |
70 | mmp->UniqueIdLength = (USHORT)(unique_id.length() * sizeof(WCHAR));
71 | memcpy((uint8_t*)mmp + mmp->UniqueIdOffset, unique_id.data(), unique_id.length() * sizeof(WCHAR));
72 | }
73 |
74 | if (device_name.length() > 0) {
75 | if (mmp->SymbolicLinkNameLength == 0 && mmp->UniqueIdOffset == 0)
76 | mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
77 | else if (mmp->SymbolicLinkNameLength != 0)
78 | mmp->DeviceNameOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
79 | else
80 | mmp->DeviceNameOffset = mmp->UniqueIdOffset + mmp->UniqueIdLength;
81 |
82 | mmp->DeviceNameLength = (USHORT)(device_name.length() * sizeof(WCHAR));
83 | memcpy((uint8_t*)mmp + mmp->DeviceNameOffset, device_name.data(), device_name.length() * sizeof(WCHAR));
84 | }
85 |
86 | vector buf2(sizeof(MOUNTMGR_MOUNT_POINTS));
87 | auto mmps = reinterpret_cast(buf2.data());
88 |
89 | Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_DELETE_POINTS,
90 | buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
91 |
92 | if (Status == STATUS_BUFFER_OVERFLOW) {
93 | buf2.resize(mmps->Size);
94 |
95 | Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_DELETE_POINTS,
96 | buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
97 | }
98 |
99 | if (!NT_SUCCESS(Status))
100 | throw ntstatus_error(Status);
101 | }
102 |
103 | vector mountmgr::query_points(wstring_view symlink, wstring_view unique_id, wstring_view device_name) const {
104 | NTSTATUS Status;
105 | IO_STATUS_BLOCK iosb;
106 | vector v;
107 |
108 | vector buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR)));
109 | auto mmp = reinterpret_cast(buf.data());
110 |
111 | memset(mmp, 0, sizeof(MOUNTMGR_MOUNT_POINT));
112 |
113 | if (symlink.length() > 0) {
114 | mmp->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
115 | mmp->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
116 | memcpy((uint8_t*)mmp + mmp->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
117 | }
118 |
119 | if (unique_id.length() > 0) {
120 | if (mmp->SymbolicLinkNameLength == 0)
121 | mmp->UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINT);
122 | else
123 | mmp->UniqueIdOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
124 |
125 | mmp->UniqueIdLength = (USHORT)(unique_id.length() * sizeof(WCHAR));
126 | memcpy((uint8_t*)mmp + mmp->UniqueIdOffset, unique_id.data(), unique_id.length() * sizeof(WCHAR));
127 | }
128 |
129 | if (device_name.length() > 0) {
130 | if (mmp->SymbolicLinkNameLength == 0 && mmp->UniqueIdOffset == 0)
131 | mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
132 | else if (mmp->SymbolicLinkNameLength != 0)
133 | mmp->DeviceNameOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
134 | else
135 | mmp->DeviceNameOffset = mmp->UniqueIdOffset + mmp->UniqueIdLength;
136 |
137 | mmp->DeviceNameLength = (USHORT)(device_name.length() * sizeof(WCHAR));
138 | memcpy((uint8_t*)mmp + mmp->DeviceNameOffset, device_name.data(), device_name.length() * sizeof(WCHAR));
139 | }
140 |
141 | vector buf2(sizeof(MOUNTMGR_MOUNT_POINTS));
142 | auto mmps = reinterpret_cast(buf2.data());
143 |
144 | Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
145 | buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
146 |
147 | if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
148 | throw ntstatus_error(Status);
149 |
150 | buf2.resize(mmps->Size);
151 | mmps = reinterpret_cast(buf2.data());
152 |
153 | Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
154 | buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
155 |
156 | if (!NT_SUCCESS(Status))
157 | throw ntstatus_error(Status);
158 |
159 | for (ULONG i = 0; i < mmps->NumberOfMountPoints; i++) {
160 | wstring_view mpsl, mpdn;
161 | string_view mpuid;
162 |
163 | if (mmps->MountPoints[i].SymbolicLinkNameLength)
164 | mpsl = wstring_view((WCHAR*)((uint8_t*)mmps + mmps->MountPoints[i].SymbolicLinkNameOffset), mmps->MountPoints[i].SymbolicLinkNameLength / sizeof(WCHAR));
165 |
166 | if (mmps->MountPoints[i].UniqueIdLength)
167 | mpuid = string_view((char*)((uint8_t*)mmps + mmps->MountPoints[i].UniqueIdOffset), mmps->MountPoints[i].UniqueIdLength);
168 |
169 | if (mmps->MountPoints[i].DeviceNameLength)
170 | mpdn = wstring_view((WCHAR*)((uint8_t*)mmps + mmps->MountPoints[i].DeviceNameOffset), mmps->MountPoints[i].DeviceNameLength / sizeof(WCHAR));
171 |
172 | v.emplace_back(mpsl, mpuid, mpdn);
173 | }
174 |
175 | return v;
176 | }
177 |
--------------------------------------------------------------------------------
/src/shellext/mountmgr.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | class mountmgr_point {
11 | public:
12 | mountmgr_point(std::wstring_view symlink, std::string_view unique_id, std::wstring_view device_name) : symlink(symlink), device_name(device_name), unique_id(unique_id) {
13 | }
14 |
15 | std::wstring symlink, device_name;
16 | std::string unique_id;
17 | };
18 |
19 | class mountmgr {
20 | public:
21 | mountmgr();
22 | ~mountmgr();
23 | void create_point(std::wstring_view symlink, std::wstring_view device) const;
24 | void delete_points(std::wstring_view symlink, std::wstring_view unique_id = L"", std::wstring_view device_name = L"") const;
25 | std::vector query_points(std::wstring_view symlink = L"", std::wstring_view unique_id = L"", std::wstring_view device_name = L"") const;
26 |
27 | private:
28 | HANDLE h;
29 | };
30 |
--------------------------------------------------------------------------------
/src/shellext/propsheet.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include
22 | #include "../btrfsioctl.h"
23 |
24 | #ifndef S_IRUSR
25 | #define S_IRUSR 0000400
26 | #endif
27 |
28 | #ifndef S_IWUSR
29 | #define S_IWUSR 0000200
30 | #endif
31 |
32 | #ifndef S_IXUSR
33 | #define S_IXUSR 0000100
34 | #endif
35 |
36 | #ifndef S_IRGRP
37 | #define S_IRGRP (S_IRUSR >> 3)
38 | #endif
39 |
40 | #ifndef S_IWGRP
41 | #define S_IWGRP (S_IWUSR >> 3)
42 | #endif
43 |
44 | #ifndef S_IXGRP
45 | #define S_IXGRP (S_IXUSR >> 3)
46 | #endif
47 |
48 | #ifndef S_IROTH
49 | #define S_IROTH (S_IRGRP >> 3)
50 | #endif
51 |
52 | #ifndef S_IWOTH
53 | #define S_IWOTH (S_IWGRP >> 3)
54 | #endif
55 |
56 | #ifndef S_IXOTH
57 | #define S_IXOTH (S_IXGRP >> 3)
58 | #endif
59 |
60 | #ifndef S_ISUID
61 | #define S_ISUID 0004000
62 | #endif
63 |
64 | #ifndef S_ISGID
65 | #define S_ISGID 0002000
66 | #endif
67 |
68 | #ifndef S_ISVTX
69 | #define S_ISVTX 0001000
70 | #endif
71 |
72 | #define BTRFS_INODE_NODATASUM 0x001
73 | #define BTRFS_INODE_NODATACOW 0x002
74 | #define BTRFS_INODE_READONLY 0x004
75 | #define BTRFS_INODE_NOCOMPRESS 0x008
76 | #define BTRFS_INODE_PREALLOC 0x010
77 | #define BTRFS_INODE_SYNC 0x020
78 | #define BTRFS_INODE_IMMUTABLE 0x040
79 | #define BTRFS_INODE_APPEND 0x080
80 | #define BTRFS_INODE_NODUMP 0x100
81 | #define BTRFS_INODE_NOATIME 0x200
82 | #define BTRFS_INODE_DIRSYNC 0x400
83 | #define BTRFS_INODE_COMPRESS 0x800
84 |
85 | extern LONG objs_loaded;
86 |
87 | class BtrfsPropSheet : public IShellExtInit, IShellPropSheetExt {
88 | public:
89 | BtrfsPropSheet() {
90 | refcount = 0;
91 | ignore = true;
92 | stgm_set = false;
93 | readonly = false;
94 | flags_changed = false;
95 | perms_changed = false;
96 | uid_changed = false;
97 | gid_changed = false;
98 | compress_type_changed = false;
99 | ro_changed = false;
100 | can_change_perms = false;
101 | show_admin_button = false;
102 | thread = nullptr;
103 | mode = mode_set = 0;
104 | flags = flags_set = 0;
105 | has_subvols = false;
106 | filename = L"";
107 |
108 | sizes[0] = sizes[1] = sizes[2] = sizes[3] = sizes[4] = 0;
109 | totalsize = allocsize = sparsesize = 0;
110 | num_extents = 0;
111 | sector_size = 0;
112 | size_format[0] = 0;
113 | cr_format[0] = 0;
114 | frag_format[0] = 0;
115 |
116 | InterlockedIncrement(&objs_loaded);
117 | }
118 |
119 | virtual ~BtrfsPropSheet() {
120 | if (stgm_set)
121 | ReleaseStgMedium(&stgm);
122 |
123 | InterlockedDecrement(&objs_loaded);
124 | }
125 |
126 | // IUnknown
127 |
128 | HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
129 |
130 | ULONG __stdcall AddRef() {
131 | return InterlockedIncrement(&refcount);
132 | }
133 |
134 | ULONG __stdcall Release() {
135 | LONG rc = InterlockedDecrement(&refcount);
136 |
137 | if (rc == 0)
138 | delete this;
139 |
140 | return rc;
141 | }
142 |
143 | // IShellExtInit
144 |
145 | virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) override;
146 |
147 | // IShellPropSheetExt
148 |
149 | virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) override;
150 | virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam) override;
151 |
152 | void init_propsheet(HWND hwndDlg);
153 | void change_inode_flag(HWND hDlg, uint64_t flag, UINT state);
154 | void change_perm_flag(HWND hDlg, ULONG perm, UINT state);
155 | void change_uid(HWND hDlg, uint32_t uid);
156 | void change_gid(HWND hDlg, uint32_t gid);
157 | void apply_changes(HWND hDlg);
158 | void set_size_on_disk(HWND hwndDlg);
159 | DWORD search_list_thread();
160 | void do_search(const wstring& fn);
161 | void update_size_details_dialog(HWND hDlg);
162 | void open_as_admin(HWND hwndDlg);
163 | void set_cmdline(const wstring& cmdline);
164 |
165 | bool readonly;
166 | bool can_change_perms;
167 | bool can_change_nocow;
168 | WCHAR size_format[255], cr_format[255], frag_format[255];
169 | HANDLE thread;
170 | uint32_t min_mode, max_mode, mode, mode_set;
171 | uint64_t min_flags, max_flags, flags, flags_set;
172 | uint64_t subvol, inode, rdev;
173 | uint8_t type, min_compression_type, max_compression_type, compress_type;
174 | uint32_t uid, gid;
175 | bool various_subvols, various_inodes, various_types, various_uids, various_gids, compress_type_changed, has_subvols,
176 | ro_subvol, various_ro, ro_changed, show_admin_button;
177 |
178 | private:
179 | LONG refcount;
180 | bool ignore;
181 | STGMEDIUM stgm;
182 | bool stgm_set;
183 | bool flags_changed, perms_changed, uid_changed, gid_changed;
184 | uint64_t sizes[5], totalsize, allocsize, sparsesize, num_extents;
185 | deque search_list;
186 | wstring filename;
187 | uint32_t sector_size;
188 |
189 | void apply_changes_file(HWND hDlg, const wstring& fn);
190 | HRESULT check_file(const wstring& fn, UINT i, UINT num_files, UINT* sv);
191 | HRESULT load_file_list();
192 | };
193 |
--------------------------------------------------------------------------------
/src/shellext/recv.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2017
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include "../btrfs.h"
22 |
23 | extern LONG objs_loaded;
24 |
25 | typedef struct {
26 | BTRFS_UUID uuid;
27 | uint64_t transid;
28 | wstring path;
29 | } subvol_cache;
30 |
31 | class BtrfsRecv {
32 | public:
33 | BtrfsRecv() {
34 | thread = nullptr;
35 | master = INVALID_HANDLE_VALUE;
36 | dir = INVALID_HANDLE_VALUE;
37 | running = false;
38 | cancelling = false;
39 | stransid = 0;
40 | num_received = 0;
41 | hwnd = nullptr;
42 | cache.clear();
43 | }
44 |
45 | virtual ~BtrfsRecv() {
46 | cache.clear();
47 | }
48 |
49 | void Open(HWND hwnd, const wstring& file, const wstring& path, bool quiet);
50 | DWORD recv_thread();
51 | INT_PTR CALLBACK RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
52 |
53 | private:
54 | void cmd_subvol(btrfs_send_command* cmd, uint8_t* data, const win_handle& parent);
55 | void cmd_snapshot(btrfs_send_command* cmd, uint8_t* data, const win_handle& parent);
56 | void cmd_mkfile(btrfs_send_command* cmd, uint8_t* data);
57 | void cmd_rename(btrfs_send_command* cmd, uint8_t* data);
58 | void cmd_link(btrfs_send_command* cmd, uint8_t* data);
59 | void cmd_unlink(btrfs_send_command* cmd, uint8_t* data);
60 | void cmd_rmdir(btrfs_send_command* cmd, uint8_t* data);
61 | void cmd_setxattr(btrfs_send_command* cmd, uint8_t* data);
62 | void cmd_removexattr(btrfs_send_command* cmd, uint8_t* data);
63 | void cmd_write(btrfs_send_command* cmd, uint8_t* data);
64 | void cmd_clone(btrfs_send_command* cmd, uint8_t* data);
65 | void cmd_truncate(btrfs_send_command* cmd, uint8_t* data);
66 | void cmd_chmod(btrfs_send_command* cmd, uint8_t* data);
67 | void cmd_chown(btrfs_send_command* cmd, uint8_t* data);
68 | void cmd_utimes(btrfs_send_command* cmd, uint8_t* data);
69 | void add_cache_entry(BTRFS_UUID* uuid, uint64_t transid, const wstring& path);
70 | bool find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len);
71 | void do_recv(const win_handle& f, uint64_t* pos, uint64_t size, const win_handle& parent);
72 |
73 | HANDLE dir, master, thread, lastwritefile;
74 | HWND hwnd;
75 | wstring streamfile, dirpath, subvolpath, lastwritepath;
76 | DWORD lastwriteatt;
77 | ULONG num_received;
78 | uint64_t stransid;
79 | BTRFS_UUID subvol_uuid;
80 | bool running, cancelling;
81 | vector cache;
82 | };
83 |
--------------------------------------------------------------------------------
/src/shellext/scrub.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2017
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include "../btrfs.h"
22 | #include "../btrfsioctl.h"
23 |
24 | class BtrfsScrub {
25 | public:
26 | BtrfsScrub(const wstring& drive) {
27 | fn = drive;
28 | }
29 |
30 | INT_PTR CALLBACK ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
31 |
32 | private:
33 | void RefreshScrubDlg(HWND hwndDlg, bool first_time);
34 | void UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs);
35 | void StartScrub(HWND hwndDlg);
36 | void PauseScrub(HWND hwndDlg);
37 | void StopScrub(HWND hwndDlg);
38 |
39 | wstring fn;
40 | uint32_t status;
41 | uint64_t chunks_left;
42 | uint32_t num_errors;
43 | };
44 |
--------------------------------------------------------------------------------
/src/shellext/send.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2017
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include "../btrfs.h"
21 |
22 | class BtrfsSend {
23 | public:
24 | BtrfsSend() {
25 | started = false;
26 | file[0] = 0;
27 | dirh = INVALID_HANDLE_VALUE;
28 | stream = INVALID_HANDLE_VALUE;
29 | subvol = L"";
30 | buf = nullptr;
31 | incremental = false;
32 | }
33 |
34 | ~BtrfsSend() {
35 | if (buf)
36 | free(buf);
37 | }
38 |
39 | void Open(HWND hwnd, WCHAR* path);
40 | INT_PTR SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
41 | DWORD Thread();
42 |
43 | private:
44 | void StartSend(HWND hwnd);
45 | void Browse(HWND hwnd);
46 | void BrowseParent(HWND hwnd);
47 | void AddClone(HWND hwnd);
48 | void RemoveClone(HWND hwnd);
49 |
50 | bool started;
51 | bool incremental;
52 | WCHAR file[MAX_PATH], closetext[255];
53 | HANDLE thread, dirh, stream;
54 | HWND hwnd;
55 | wstring subvol;
56 | char* buf;
57 | vector clones;
58 | };
59 |
--------------------------------------------------------------------------------
/src/shellext/shellbtrfs.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | DllCanUnloadNow PRIVATE
3 | DllGetClassObject PRIVATE
4 | DllRegisterServer PRIVATE
5 | DllUnregisterServer PRIVATE
6 | DllInstall PRIVATE
7 | AddDeviceW PRIVATE
8 | RemoveDeviceW PRIVATE
9 | StartBalanceW PRIVATE
10 | PauseBalanceW PRIVATE
11 | StopBalanceW PRIVATE
12 | ShowScrubW PRIVATE
13 | ResetStatsW PRIVATE
14 | ShowPropSheetW PRIVATE
15 | RecvSubvolGUIW PRIVATE
16 | SendSubvolGUIW PRIVATE
17 | CreateSubvolW PRIVATE
18 | CreateSnapshotW PRIVATE
19 | ReflinkCopyW PRIVATE
20 | StartScrubW PRIVATE
21 | StopScrubW PRIVATE
22 | SendSubvolW PRIVATE
23 | RecvSubvolW PRIVATE
24 | ResizeDeviceW PRIVATE
25 | ShowChangeDriveLetterW PRIVATE
26 | MappingsTest PRIVATE
27 |
--------------------------------------------------------------------------------
/src/shellext/shellbtrfs.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinBtrfs shell extension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/shellext/shellext.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #define ISOLATION_AWARE_ENABLED 1
21 | #define STRSAFE_NO_DEPRECATE
22 |
23 | #define WINVER 0x0A00 // Windows 10
24 | #define _WIN32_WINNT 0x0A00
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include "../btrfs.h"
32 | #include "../btrfsioctl.h"
33 |
34 | using namespace std;
35 |
36 | #define STATUS_SUCCESS (NTSTATUS)0x00000000
37 | #define STATUS_BUFFER_OVERFLOW (NTSTATUS)0x80000005
38 | #define STATUS_END_OF_FILE (NTSTATUS)0xc0000011
39 | #define STATUS_MORE_PROCESSING_REQUIRED (NTSTATUS)0xc0000016
40 | #define STATUS_BUFFER_TOO_SMALL (NTSTATUS)0xc0000023
41 | #define STATUS_DEVICE_NOT_READY (NTSTATUS)0xc00000a3
42 | #define STATUS_CANNOT_DELETE (NTSTATUS)0xc0000121
43 | #define STATUS_NOT_FOUND (NTSTATUS)0xc0000225
44 |
45 | #define BLOCK_FLAG_DATA 0x001
46 | #define BLOCK_FLAG_SYSTEM 0x002
47 | #define BLOCK_FLAG_METADATA 0x004
48 | #define BLOCK_FLAG_RAID0 0x008
49 | #define BLOCK_FLAG_RAID1 0x010
50 | #define BLOCK_FLAG_DUPLICATE 0x020
51 | #define BLOCK_FLAG_RAID10 0x040
52 | #define BLOCK_FLAG_RAID5 0x080
53 | #define BLOCK_FLAG_RAID6 0x100
54 |
55 | #define BTRFS_TYPE_FILE 1
56 | #define BTRFS_TYPE_DIRECTORY 2
57 | #define BTRFS_TYPE_CHARDEV 3
58 | #define BTRFS_TYPE_BLOCKDEV 4
59 | #define BTRFS_TYPE_FIFO 5
60 | #define BTRFS_TYPE_SOCKET 6
61 | #define BTRFS_TYPE_SYMLINK 7
62 |
63 | #ifdef _MSC_VER
64 | #define funcname __FUNCTION__
65 | #else
66 | #define funcname __func__
67 | #endif
68 |
69 | #ifdef _MSC_VER
70 | #pragma warning(disable: 4800)
71 | #endif
72 |
73 | extern "C" {
74 | NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer,
75 | ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
76 |
77 | NTSTATUS WINAPI NtSetEaFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length);
78 |
79 | NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor);
80 |
81 | #ifdef _MSC_VER
82 | NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
83 | PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength,
84 | PVOID OutputBuffer, ULONG OutputBufferLength);
85 | NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass);
86 |
87 | NTSTATUS NTAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass);
88 |
89 | #define FileBasicInformation (FILE_INFORMATION_CLASS)4
90 | #define FileStandardInformation (FILE_INFORMATION_CLASS)5
91 | #define FileDispositionInformation (FILE_INFORMATION_CLASS)13
92 | #define FileEndOfFileInformation (FILE_INFORMATION_CLASS)20
93 | #define FileStreamInformation (FILE_INFORMATION_CLASS)22
94 |
95 | typedef enum _FSINFOCLASS {
96 | FileFsVolumeInformation = 1,
97 | FileFsLabelInformation,
98 | FileFsSizeInformation,
99 | FileFsDeviceInformation,
100 | FileFsAttributeInformation,
101 | FileFsControlInformation,
102 | FileFsFullSizeInformation,
103 | FileFsObjectIdInformation,
104 | FileFsDriverPathInformation,
105 | FileFsVolumeFlagsInformation,
106 | FileFsSectorSizeInformation,
107 | FileFsDataCopyInformation,
108 | FileFsMetadataSizeInformation,
109 | FileFsFullSizeInformationEx,
110 | FileFsMaximumInformation
111 | } FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
112 |
113 | typedef struct _FILE_STREAM_INFORMATION {
114 | ULONG NextEntryOffset;
115 | ULONG StreamNameLength;
116 | LARGE_INTEGER StreamSize;
117 | LARGE_INTEGER StreamAllocationSize;
118 | WCHAR StreamName[1];
119 | } FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
120 | #endif
121 |
122 | NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length,
123 | FS_INFORMATION_CLASS FsInformationClass);
124 | }
125 |
126 | typedef struct _REPARSE_DATA_BUFFER {
127 | ULONG ReparseTag;
128 | USHORT ReparseDataLength;
129 | USHORT Reserved;
130 |
131 | union {
132 | struct {
133 | USHORT SubstituteNameOffset;
134 | USHORT SubstituteNameLength;
135 | USHORT PrintNameOffset;
136 | USHORT PrintNameLength;
137 | ULONG Flags;
138 | WCHAR PathBuffer[1];
139 | } SymbolicLinkReparseBuffer;
140 |
141 | struct {
142 | USHORT SubstituteNameOffset;
143 | USHORT SubstituteNameLength;
144 | USHORT PrintNameOffset;
145 | USHORT PrintNameLength;
146 | WCHAR PathBuffer[1];
147 | } MountPointReparseBuffer;
148 |
149 | struct {
150 | UCHAR DataBuffer[1];
151 | } GenericReparseBuffer;
152 | };
153 | } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
154 |
155 | #define SYMLINK_FLAG_RELATIVE 1
156 |
157 | #ifndef _MSC_VER
158 |
159 | typedef struct _DUPLICATE_EXTENTS_DATA {
160 | HANDLE FileHandle;
161 | LARGE_INTEGER SourceFileOffset;
162 | LARGE_INTEGER TargetFileOffset;
163 | LARGE_INTEGER ByteCount;
164 | } DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
165 |
166 | typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
167 | WORD ChecksumAlgorithm;
168 | WORD Reserved;
169 | DWORD Flags;
170 | DWORD ChecksumChunkSizeInBytes;
171 | DWORD ClusterSizeInBytes;
172 | } FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER;
173 |
174 | typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
175 | WORD ChecksumAlgorithm;
176 | WORD Reserved;
177 | DWORD Flags;
178 | } FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER;
179 |
180 | #endif
181 |
182 | class win_handle {
183 | public:
184 | win_handle() {
185 | }
186 |
187 | win_handle(HANDLE nh) {
188 | h = nh;
189 | }
190 |
191 | ~win_handle() {
192 | if (h != INVALID_HANDLE_VALUE)
193 | CloseHandle(h);
194 | }
195 |
196 | operator HANDLE() const {
197 | return h;
198 | }
199 |
200 | win_handle& operator=(const HANDLE nh) {
201 | if (h != INVALID_HANDLE_VALUE)
202 | CloseHandle(h);
203 |
204 | h = nh;
205 |
206 | return *this;
207 | }
208 |
209 | HANDLE* operator&() {
210 | return &h;
211 | }
212 |
213 | private:
214 | HANDLE h = INVALID_HANDLE_VALUE;
215 | };
216 |
217 | class fff_handle {
218 | public:
219 | fff_handle() {
220 | }
221 |
222 | fff_handle(HANDLE nh) {
223 | h = nh;
224 | }
225 |
226 | ~fff_handle() {
227 | if (h != INVALID_HANDLE_VALUE)
228 | FindClose(h);
229 | }
230 |
231 | operator HANDLE() const {
232 | return h;
233 | }
234 |
235 | fff_handle& operator=(const HANDLE nh) {
236 | if (h != INVALID_HANDLE_VALUE)
237 | FindClose(h);
238 |
239 | h = nh;
240 |
241 | return *this;
242 | }
243 |
244 | HANDLE* operator&() {
245 | return &h;
246 | }
247 |
248 | private:
249 | HANDLE h = INVALID_HANDLE_VALUE;
250 | };
251 |
252 | class nt_handle {
253 | public:
254 | nt_handle() {
255 | }
256 |
257 | nt_handle(HANDLE nh) {
258 | h = nh;
259 | }
260 |
261 | ~nt_handle() {
262 | if (h != INVALID_HANDLE_VALUE)
263 | NtClose(h);
264 | }
265 |
266 | operator HANDLE() const {
267 | return h;
268 | }
269 |
270 | nt_handle& operator=(const HANDLE nh) {
271 | if (h != INVALID_HANDLE_VALUE)
272 | NtClose(h);
273 |
274 | h = nh;
275 |
276 | return *this;
277 | }
278 |
279 | HANDLE* operator&() {
280 | return &h;
281 | }
282 |
283 | private:
284 | HANDLE h = INVALID_HANDLE_VALUE;
285 | };
286 |
287 | class string_error : public exception {
288 | public:
289 | string_error(int resno, ...);
290 |
291 | const char* what() const noexcept {
292 | return msg.c_str();
293 | }
294 |
295 | private:
296 | string msg;
297 | };
298 |
299 |
300 | class last_error : public exception {
301 | public:
302 | last_error(DWORD errnum);
303 |
304 | const char* what() const noexcept {
305 | return msg.c_str();
306 | }
307 |
308 | private:
309 | string msg;
310 | };
311 |
312 | class ntstatus_error : public exception {
313 | public:
314 | ntstatus_error(NTSTATUS Status);
315 |
316 | const char* what() const noexcept {
317 | return msg.c_str();
318 | }
319 |
320 | NTSTATUS Status;
321 |
322 | private:
323 | string msg;
324 | };
325 |
326 | class global_lock {
327 | public:
328 | global_lock(HGLOBAL mem) : mem(mem) {
329 | ptr = GlobalLock(mem);
330 | }
331 |
332 | ~global_lock() {
333 | if (ptr)
334 | GlobalUnlock(mem);
335 | }
336 |
337 | void* ptr;
338 |
339 | private:
340 | HGLOBAL mem;
341 | };
342 |
343 | extern HMODULE module;
344 | void format_size(uint64_t size, wstring& s, bool show_bytes);
345 | void set_dpi_aware();
346 | wstring format_message(ULONG last_error);
347 | wstring format_ntstatus(NTSTATUS Status);
348 | bool load_string(HMODULE module, UINT id, wstring& s);
349 | void wstring_sprintf(wstring& s, wstring fmt, ...);
350 | void command_line_to_args(LPWSTR cmdline, vector& args);
351 | wstring utf8_to_utf16(string_view utf8);
352 | void error_message(HWND hwnd, const char* msg);
353 |
--------------------------------------------------------------------------------
/src/shellext/subvol.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maharmstone/btrfs/ce2997cbe111f0a57523af456c805a32fb7b4591/src/shellext/subvol.ico
--------------------------------------------------------------------------------
/src/shellext/volpropsheet.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #pragma once
19 |
20 | #include
21 | #include "../btrfsioctl.h"
22 | #include "../btrfs.h"
23 | #include "balance.h"
24 | #include "scrub.h"
25 |
26 | extern LONG objs_loaded;
27 |
28 | class BtrfsVolPropSheet : public IShellExtInit, IShellPropSheetExt {
29 | public:
30 | BtrfsVolPropSheet() {
31 | refcount = 0;
32 | ignore = true;
33 | stgm_set = false;
34 | devices = nullptr;
35 |
36 | InterlockedIncrement(&objs_loaded);
37 |
38 | balance = nullptr;
39 | }
40 |
41 | virtual ~BtrfsVolPropSheet() {
42 | if (stgm_set)
43 | ReleaseStgMedium(&stgm);
44 |
45 | if (devices)
46 | free(devices);
47 |
48 | InterlockedDecrement(&objs_loaded);
49 |
50 | if (balance)
51 | delete balance;
52 | }
53 |
54 | // IUnknown
55 |
56 | HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
57 |
58 | ULONG __stdcall AddRef() {
59 | return InterlockedIncrement(&refcount);
60 | }
61 |
62 | ULONG __stdcall Release() {
63 | LONG rc = InterlockedDecrement(&refcount);
64 |
65 | if (rc == 0)
66 | delete this;
67 |
68 | return rc;
69 | }
70 |
71 | // IShellExtInit
72 |
73 | virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) override;
74 |
75 | // IShellPropSheetExt
76 |
77 | virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) override;
78 | virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam) override;
79 |
80 | void FormatUsage(HWND hwndDlg, wstring& s, btrfs_usage* usage);
81 | void RefreshUsage(HWND hwndDlg);
82 | void ShowUsage(HWND hwndDlg);
83 | INT_PTR CALLBACK UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
84 | void RefreshDevList(HWND devlist);
85 | INT_PTR CALLBACK DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
86 | void ShowDevices(HWND hwndDlg);
87 | void ShowScrub(HWND hwndDlg);
88 | void ShowChangeDriveLetter(HWND hwndDlg);
89 | INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
90 | void ShowStats(HWND hwndDlg, uint64_t devid);
91 | void ResetStats(HWND hwndDlg);
92 |
93 | btrfs_device* devices;
94 | bool readonly;
95 | BtrfsBalance* balance;
96 | BTRFS_UUID uuid;
97 | bool uuid_set;
98 |
99 | private:
100 | LONG refcount;
101 | bool ignore;
102 | STGMEDIUM stgm;
103 | bool stgm_set;
104 | wstring fn;
105 | uint64_t stats_dev;
106 | };
107 |
108 | class BtrfsChangeDriveLetter {
109 | public:
110 | BtrfsChangeDriveLetter(HWND hwnd, wstring_view fn) : hwnd(hwnd), fn(fn) {
111 | }
112 |
113 | void show();
114 | INT_PTR DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
115 |
116 | private:
117 | void do_change(HWND hwndDlg);
118 |
119 | HWND hwnd;
120 | wstring fn;
121 | vector letters;
122 | };
123 |
--------------------------------------------------------------------------------
/src/tests/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | UTF-8
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/tests/overwrite.cpp:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | using namespace std;
4 |
5 | void test_overwrite(const u16string& dir) {
6 | unique_handle h;
7 |
8 | test("Try overwriting non-existent file", [&]() {
9 | exp_status([&]() {
10 | create_file(dir + u"\\nonsuch", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
11 | 0, FILE_OVERWRITTEN);
12 | }, STATUS_OBJECT_NAME_NOT_FOUND);
13 | });
14 |
15 | test("Create readonly file", [&]() {
16 | h = create_file(dir + u"\\overwritero", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATE,
17 | 0, FILE_CREATED);
18 | });
19 |
20 | if (h) {
21 | h.reset();
22 |
23 | test("Try overwriting readonly file", [&]() {
24 | exp_status([&]() {
25 | create_file(dir + u"\\overwritero", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
26 | 0, FILE_OVERWRITTEN);
27 | }, STATUS_ACCESS_DENIED);
28 | });
29 | }
30 |
31 | test("Create file", [&]() {
32 | h = create_file(dir + u"\\overwrite", MAXIMUM_ALLOWED, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
33 | FILE_CREATE, 0, FILE_CREATED);
34 | });
35 |
36 | if (h) {
37 | test("Try overwriting open file", [&]() {
38 | create_file(dir + u"\\overwrite", MAXIMUM_ALLOWED, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
39 | FILE_OVERWRITE, 0, FILE_OVERWRITTEN);
40 | });
41 |
42 | h.reset();
43 |
44 | test("Overwrite file", [&]() {
45 | h = create_file(dir + u"\\overwrite", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
46 | 0, FILE_OVERWRITTEN);
47 | });
48 | }
49 |
50 | if (h) {
51 | h.reset();
52 |
53 | test("Overwrite file adding readonly flag", [&]() {
54 | create_file(dir + u"\\overwrite", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITE,
55 | 0, FILE_OVERWRITTEN);
56 | });
57 | }
58 |
59 | test("Create file", [&]() {
60 | h = create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, 0, 0, FILE_CREATE,
61 | 0, FILE_CREATED);
62 | });
63 |
64 | if (h) {
65 | h.reset();
66 |
67 | test("Try overwriting file, changing to directory", [&]() {
68 | exp_status([&]() {
69 | create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
70 | FILE_DIRECTORY_FILE, FILE_OVERWRITTEN);
71 | }, STATUS_INVALID_PARAMETER);
72 | });
73 |
74 | test("Overwrite file adding hidden flag", [&]() {
75 | h = create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN, 0, FILE_OVERWRITE,
76 | 0, FILE_OVERWRITTEN);
77 | });
78 | }
79 |
80 | if (h) {
81 | h.reset();
82 |
83 | test("Try overwriting file clearing hidden flag", [&]() {
84 | exp_status([&]() {
85 | create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
86 | 0, FILE_OVERWRITTEN);
87 | }, STATUS_ACCESS_DENIED);
88 | });
89 | }
90 |
91 | test("Overwrite file adding system flag", [&]() {
92 | h = create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 0,
93 | FILE_OVERWRITE, 0, FILE_OVERWRITTEN);
94 | });
95 |
96 | if (h) {
97 | h.reset();
98 |
99 | test("Try overwriting file clearing system flag", [&]() {
100 | exp_status([&]() {
101 | create_file(dir + u"\\overwrite2", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN, 0, FILE_OVERWRITE,
102 | 0, FILE_OVERWRITTEN);
103 | }, STATUS_ACCESS_DENIED);
104 | });
105 | }
106 |
107 | test("Create directory", [&]() {
108 | h = create_file(dir + u"\\overwritedir", MAXIMUM_ALLOWED, 0, 0, FILE_CREATE,
109 | FILE_DIRECTORY_FILE, FILE_CREATED);
110 | });
111 |
112 | if (h) {
113 | h.reset();
114 |
115 | test("Try overwriting directory", [&]() {
116 | exp_status([&]() {
117 | create_file(dir + u"\\overwritedir", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
118 | FILE_DIRECTORY_FILE, FILE_OVERWRITTEN);
119 | }, STATUS_INVALID_PARAMETER);
120 | });
121 |
122 | test("Try overwriting directory, changing to file", [&]() {
123 | exp_status([&]() {
124 | create_file(dir + u"\\overwritedir", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
125 | FILE_NON_DIRECTORY_FILE, FILE_OVERWRITTEN);
126 | }, STATUS_FILE_IS_A_DIRECTORY);
127 | });
128 | }
129 |
130 | test("Create file", [&]() {
131 | h = create_file(dir + u"\\overwrite3", MAXIMUM_ALLOWED, 0, 0, FILE_CREATE,
132 | 0, FILE_CREATED);
133 | });
134 |
135 | if (h) {
136 | h.reset();
137 |
138 | test("Overwrite file with different case", [&]() {
139 | h = create_file(dir + u"\\OVERWRITE3", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE,
140 | 0, FILE_OVERWRITTEN);
141 | });
142 |
143 | if (h) {
144 | test("Check name", [&]() {
145 | auto fn = query_file_name_information(h.get());
146 |
147 | static const u16string_view ends_with = u"\\overwrite3";
148 |
149 | if (fn.size() < ends_with.size() || fn.substr(fn.size() - ends_with.size()) != ends_with)
150 | throw runtime_error("Name did not end with \"\\overwrite3\".");
151 | });
152 | }
153 | }
154 |
155 | test("Create file with FILE_OPEN_IF", [&]() {
156 | h = create_file(dir + u"\\overwriteif", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE_IF, 0, FILE_CREATED);
157 | });
158 |
159 | if (h) {
160 | h.reset();
161 |
162 | test("Open file with FILE_OVERWRITE_IF", [&]() {
163 | create_file(dir + u"\\overwriteif", MAXIMUM_ALLOWED, 0, 0, FILE_OVERWRITE_IF, 0, FILE_OVERWRITTEN);
164 | });
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/tests/supersede.cpp:
--------------------------------------------------------------------------------
1 | #include "test.h"
2 |
3 | using namespace std;
4 |
5 | void test_supersede(const u16string& dir) {
6 | unique_handle h;
7 |
8 | test("Create file by FILE_SUPERSEDE", [&]() {
9 | h = create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
10 | FILE_SUPERSEDE, 0, FILE_CREATED);
11 | });
12 |
13 | if (h) {
14 | test("Check attributes", [&]() {
15 | auto fbi = query_information(h.get());
16 |
17 | if (fbi.FileAttributes != (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE)) {
18 | throw formatted_error("attributes were {:x}, expected FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE",
19 | fbi.FileAttributes);
20 | }
21 | });
22 |
23 | test("Try superseding open file", [&]() {
24 | create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
25 | FILE_SUPERSEDE, 0, FILE_SUPERSEDED);
26 | });
27 |
28 | h.reset();
29 | }
30 |
31 | test("Supersede file", [&]() {
32 | h = create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, 0, 0, FILE_SUPERSEDE,
33 | 0, FILE_SUPERSEDED);
34 | });
35 |
36 | if (h) {
37 | test("Check attributes", [&]() {
38 | auto fbi = query_information(h.get());
39 |
40 | if (fbi.FileAttributes != FILE_ATTRIBUTE_ARCHIVE) {
41 | throw formatted_error("attributes were {:x}, expected FILE_ATTRIBUTE_ARCHIVE",
42 | fbi.FileAttributes);
43 | }
44 | });
45 |
46 | h.reset();
47 | }
48 |
49 | test("Supersede adding hidden flag", [&]() {
50 | create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN, 0,
51 | FILE_SUPERSEDE, 0, FILE_SUPERSEDED);
52 | });
53 |
54 | test("Try superseding while clearing hidden flag", [&]() {
55 | exp_status([&]() {
56 | create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, 0, 0, FILE_SUPERSEDE,
57 | 0, FILE_SUPERSEDED);
58 | }, STATUS_ACCESS_DENIED);
59 | });
60 |
61 | test("Supersede adding system flag", [&]() {
62 | create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 0,
63 | FILE_SUPERSEDE, 0, FILE_SUPERSEDED);
64 | });
65 |
66 | test("Try superseding while clearing system flag", [&]() {
67 | exp_status([&]() {
68 | create_file(dir + u"\\supersede", MAXIMUM_ALLOWED, FILE_ATTRIBUTE_HIDDEN, 0,
69 | FILE_SUPERSEDE, 0, FILE_SUPERSEDED);
70 | }, STATUS_ACCESS_DENIED);
71 | });
72 |
73 | test("Try creating directory by FILE_SUPERSEDE", [&]() {
74 | exp_status([&]() {
75 | create_file(dir + u"\\supersededir", MAXIMUM_ALLOWED, 0, 0, FILE_SUPERSEDE,
76 | FILE_DIRECTORY_FILE, FILE_CREATED);
77 | }, STATUS_INVALID_PARAMETER);
78 | });
79 |
80 | test("Create file", [&]() {
81 | h = create_file(dir + u"\\supersede2", MAXIMUM_ALLOWED, 0, 0, FILE_CREATE,
82 | 0, FILE_CREATED);
83 | });
84 |
85 | if (h) {
86 | h.reset();
87 |
88 | test("Supersede file with different case", [&]() {
89 | h = create_file(dir + u"\\SUPERSEDE2", MAXIMUM_ALLOWED, 0, 0, FILE_SUPERSEDE,
90 | 0, FILE_SUPERSEDED);
91 | });
92 |
93 | if (h) {
94 | test("Check name", [&]() {
95 | auto fn = query_file_name_information(h.get());
96 |
97 | static const u16string_view ends_with = u"\\supersede2";
98 |
99 | if (fn.size() < ends_with.size() || fn.substr(fn.size() - ends_with.size()) != ends_with)
100 | throw runtime_error("Name did not end with \"\\supersede2\".");
101 | });
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/tests/test.rc.in:
--------------------------------------------------------------------------------
1 | #define APSTUDIO_READONLY_SYMBOLS
2 | #include
3 | #undef APSTUDIO_READONLY_SYMBOLS
4 |
5 | /////////////////////////////////////////////////////////////////////////////
6 | // English (United Kingdom) resources
7 |
8 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
9 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
10 | #pragma code_page(1252)
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Version
15 | //
16 |
17 | VS_VERSION_INFO VERSIONINFO
18 | FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
19 | PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
20 | FILEFLAGSMASK 0x17L
21 | #ifdef _DEBUG
22 | FILEFLAGS 0x1L
23 | #else
24 | FILEFLAGS 0x0L
25 | #endif
26 | FILEOS 0x4L
27 | FILETYPE 0x1L
28 | FILESUBTYPE 0x0L
29 | BEGIN
30 | BLOCK "StringFileInfo"
31 | BEGIN
32 | BLOCK "080904b0"
33 | BEGIN
34 | VALUE "FileDescription", "WinBtrfs test program"
35 | VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
36 | VALUE "InternalName", "test"
37 | VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2021-24"
38 | VALUE "OriginalFilename", "test.exe"
39 | VALUE "ProductName", "WinBtrfs"
40 | VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
41 | END
42 | END
43 | BLOCK "VarFileInfo"
44 | BEGIN
45 | VALUE "Translation", 0x809, 1200
46 | END
47 | END
48 |
49 | 1 RT_MANIFEST "@CMAKE_CURRENT_SOURCE_DIR@/src/tests/manifest.xml"
50 |
51 | #endif // English (United Kingdom) resources
52 | /////////////////////////////////////////////////////////////////////////////
53 |
--------------------------------------------------------------------------------
/src/ubtrfs/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by ubtrfs.rc
4 | //
5 |
6 | // Next default values for new objects
7 | //
8 | #ifdef APSTUDIO_INVOKED
9 | #ifndef APSTUDIO_READONLY_SYMBOLS
10 | #define _APS_NEXT_RESOURCE_VALUE 101
11 | #define _APS_NEXT_COMMAND_VALUE 40001
12 | #define _APS_NEXT_CONTROL_VALUE 1001
13 | #define _APS_NEXT_SYMED_VALUE 101
14 | #endif
15 | #endif
16 |
--------------------------------------------------------------------------------
/src/ubtrfs/ubtrfs.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | ChkdskEx PRIVATE
3 | FormatEx PRIVATE
4 | GetFilesystemInformation PRIVATE
5 | SetSizes PRIVATE
6 | SetIncompatFlags PRIVATE
7 | SetCsumType PRIVATE
8 | SetCompatROFlags PRIVATE
9 |
--------------------------------------------------------------------------------
/src/ubtrfs/ubtrfs.rc.in:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "@CMAKE_CURRENT_SOURCE_DIR@/src/ubtrfs/resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (United Kingdom) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Version
51 | //
52 |
53 | VS_VERSION_INFO VERSIONINFO
54 | FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
55 | PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
56 | FILEFLAGSMASK 0x17L
57 | #ifdef _DEBUG
58 | FILEFLAGS 0x1L
59 | #else
60 | FILEFLAGS 0x0L
61 | #endif
62 | FILEOS 0x4L
63 | FILETYPE 0x2L
64 | FILESUBTYPE 0x0L
65 | BEGIN
66 | BLOCK "StringFileInfo"
67 | BEGIN
68 | BLOCK "080904b0"
69 | BEGIN
70 | VALUE "FileDescription", "Btrfs utility DLL"
71 | VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
72 | VALUE "InternalName", "ubtrfs"
73 | VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-24"
74 | VALUE "OriginalFilename", "ubtrfs.dll"
75 | VALUE "ProductName", "WinBtrfs"
76 | VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
77 | END
78 | END
79 | BLOCK "VarFileInfo"
80 | BEGIN
81 | VALUE "Translation", 0x809, 1200
82 | END
83 | END
84 |
85 | #endif // English (United Kingdom) resources
86 | /////////////////////////////////////////////////////////////////////////////
87 |
88 |
89 |
90 | #ifndef APSTUDIO_INVOKED
91 | /////////////////////////////////////////////////////////////////////////////
92 | //
93 | // Generated from the TEXTINCLUDE 3 resource.
94 | //
95 |
96 |
97 | /////////////////////////////////////////////////////////////////////////////
98 | #endif // not APSTUDIO_INVOKED
99 |
100 |
--------------------------------------------------------------------------------
/src/worker-thread.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2016-17
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | #include "btrfs_drv.h"
19 |
20 | typedef struct {
21 | device_extension* Vcb;
22 | PIRP Irp;
23 | WORK_QUEUE_ITEM item;
24 | } job_info;
25 |
26 | NTSTATUS do_read_job(PIRP Irp) {
27 | NTSTATUS Status;
28 | ULONG bytes_read;
29 | bool top_level = is_top_level(Irp);
30 | PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
31 | PFILE_OBJECT FileObject = IrpSp->FileObject;
32 | fcb* fcb = FileObject->FsContext;
33 | bool acquired_fcb_lock = false;
34 |
35 | Irp->IoStatus.Information = 0;
36 |
37 | if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) {
38 | ExAcquireResourceSharedLite(fcb->Header.Resource, true);
39 | acquired_fcb_lock = true;
40 | }
41 |
42 | try {
43 | Status = do_read(Irp, true, &bytes_read);
44 | } except (EXCEPTION_EXECUTE_HANDLER) {
45 | Status = GetExceptionCode();
46 | }
47 |
48 | if (acquired_fcb_lock)
49 | ExReleaseResourceLite(fcb->Header.Resource);
50 |
51 | if (!NT_SUCCESS(Status))
52 | ERR("do_read returned %08lx\n", Status);
53 |
54 | Irp->IoStatus.Status = Status;
55 |
56 | TRACE("read %Iu bytes\n", Irp->IoStatus.Information);
57 |
58 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
59 |
60 | if (top_level)
61 | IoSetTopLevelIrp(NULL);
62 |
63 | TRACE("returning %08lx\n", Status);
64 |
65 | return Status;
66 | }
67 |
68 | NTSTATUS do_write_job(device_extension* Vcb, PIRP Irp) {
69 | bool top_level = is_top_level(Irp);
70 | NTSTATUS Status;
71 |
72 | try {
73 | Status = write_file(Vcb, Irp, true, true);
74 | } except (EXCEPTION_EXECUTE_HANDLER) {
75 | Status = GetExceptionCode();
76 | }
77 |
78 | if (!NT_SUCCESS(Status))
79 | ERR("write_file returned %08lx\n", Status);
80 |
81 | Irp->IoStatus.Status = Status;
82 |
83 | TRACE("wrote %Iu bytes\n", Irp->IoStatus.Information);
84 |
85 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
86 |
87 | if (top_level)
88 | IoSetTopLevelIrp(NULL);
89 |
90 | TRACE("returning %08lx\n", Status);
91 |
92 | return Status;
93 | }
94 |
95 | _Function_class_(WORKER_THREAD_ROUTINE)
96 | static void __stdcall do_job(void* context) {
97 | job_info* ji = context;
98 | PIO_STACK_LOCATION IrpSp = ji->Irp ? IoGetCurrentIrpStackLocation(ji->Irp) : NULL;
99 |
100 | if (IrpSp->MajorFunction == IRP_MJ_READ) {
101 | do_read_job(ji->Irp);
102 | } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
103 | do_write_job(ji->Vcb, ji->Irp);
104 | }
105 |
106 | ExFreePool(ji);
107 | }
108 |
109 | bool add_thread_job(device_extension* Vcb, PIRP Irp) {
110 | job_info* ji;
111 |
112 | ji = ExAllocatePoolWithTag(NonPagedPool, sizeof(job_info), ALLOC_TAG);
113 | if (!ji) {
114 | ERR("out of memory\n");
115 | return false;
116 | }
117 |
118 | ji->Vcb = Vcb;
119 | ji->Irp = Irp;
120 |
121 | if (!Irp->MdlAddress) {
122 | PMDL Mdl;
123 | LOCK_OPERATION op;
124 | ULONG len;
125 | PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
126 |
127 | if (IrpSp->MajorFunction == IRP_MJ_READ) {
128 | op = IoWriteAccess;
129 | len = IrpSp->Parameters.Read.Length;
130 | } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
131 | op = IoReadAccess;
132 | len = IrpSp->Parameters.Write.Length;
133 | } else {
134 | ERR("unexpected major function %u\n", IrpSp->MajorFunction);
135 | ExFreePool(ji);
136 | return false;
137 | }
138 |
139 | Mdl = IoAllocateMdl(Irp->UserBuffer, len, false, false, Irp);
140 |
141 | if (!Mdl) {
142 | ERR("out of memory\n");
143 | ExFreePool(ji);
144 | return false;
145 | }
146 |
147 | try {
148 | MmProbeAndLockPages(Mdl, Irp->RequestorMode, op);
149 | } except(EXCEPTION_EXECUTE_HANDLER) {
150 | ERR("MmProbeAndLockPages raised status %08lx\n", GetExceptionCode());
151 |
152 | IoFreeMdl(Mdl);
153 | Irp->MdlAddress = NULL;
154 | ExFreePool(ji);
155 |
156 | return false;
157 | }
158 | }
159 |
160 | ExInitializeWorkItem(&ji->item, do_job, ji);
161 | ExQueueWorkItem(&ji->item, DelayedWorkQueue);
162 |
163 | return true;
164 | }
165 |
--------------------------------------------------------------------------------
/src/xor-gas.S:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Mark Harmstone 2020
2 | *
3 | * This file is part of WinBtrfs.
4 | *
5 | * WinBtrfs is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public Licence as published by
7 | * the Free Software Foundation, either version 3 of the Licence, or
8 | * (at your option) any later version.
9 | *
10 | * WinBtrfs is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public Licence for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public Licence
16 | * along with WinBtrfs. If not, see . */
17 |
18 | .intel_syntax noprefix
19 |
20 | #ifdef __x86_64__
21 |
22 | .global do_xor_sse2
23 |
24 | /* void do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */
25 | do_xor_sse2:
26 | /* rcx = buf1
27 | * rdx = buf2
28 | * r8d = len
29 | * rax = tmp1
30 | * r9 = tmp2
31 | * xmm0 = tmp3
32 | * xmm1 = tmp4 */
33 |
34 | mov rax, rcx
35 | and rax, 15
36 | cmp rax, 0
37 | jne stragglers2
38 |
39 | mov rax, rdx
40 | and rax, 15
41 | cmp rax, 0
42 | jne stragglers2
43 |
44 | do_xor_sse2_loop:
45 | cmp r8d, 16
46 | jl stragglers2
47 |
48 | movdqa xmm0, [rcx]
49 | movdqa xmm1, [rdx]
50 | pxor xmm0, xmm1
51 | movdqa [rcx], xmm0
52 |
53 | add rcx, 16
54 | add rdx, 16
55 | sub r8d, 16
56 |
57 | jmp do_xor_sse2_loop
58 |
59 | stragglers2:
60 |
61 | cmp r8d, 8
62 | jl stragglers
63 |
64 | mov rax, [rcx]
65 | mov r9, [rdx]
66 | xor rax, r9
67 | mov [rcx], rax
68 |
69 | add rcx, 8
70 | add rdx, 8
71 | sub r8d, 8
72 |
73 | jmp stragglers2
74 |
75 | stragglers:
76 |
77 | cmp r8d, 0
78 | je do_xor_sse2_end
79 |
80 | mov al, [rcx]
81 | mov r9b, [rdx]
82 | xor al, r9b
83 | mov [rcx], al
84 |
85 | inc rcx
86 | inc rdx
87 | dec r8d
88 |
89 | jmp stragglers
90 |
91 | do_xor_sse2_end:
92 | ret
93 |
94 | .global do_xor_avx2
95 |
96 | /* void do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */
97 | do_xor_avx2:
98 | /* rcx = buf1
99 | * rdx = buf2
100 | * r8d = len
101 | * rax = tmp1
102 | * r9 = tmp2
103 | * xmm0 = tmp3
104 | * xmm1 = tmp4 */
105 |
106 | mov rax, rcx
107 | and rax, 31
108 | cmp rax, 0
109 | jne stragglers4
110 |
111 | mov rax, rdx
112 | and rax, 31
113 | cmp rax, 0
114 | jne stragglers4
115 |
116 | do_xor_avx2_loop:
117 | cmp r8d, 32
118 | jl stragglers4
119 |
120 | vmovdqa ymm0, [rcx]
121 | vmovdqa ymm1, [rdx]
122 | vpxor ymm0, ymm0, ymm1
123 | vmovdqa [rcx], ymm0
124 |
125 | add rcx, 32
126 | add rdx, 32
127 | sub r8d, 32
128 |
129 | jmp do_xor_avx2_loop
130 |
131 | stragglers4:
132 |
133 | cmp r8d, 8
134 | jl stragglers3
135 |
136 | mov rax, [rcx]
137 | mov r9, [rdx]
138 | xor rax, r9
139 | mov [rcx], rax
140 |
141 | add rcx, 8
142 | add rdx, 8
143 | sub r8d, 8
144 |
145 | jmp stragglers4
146 |
147 | stragglers3:
148 |
149 | cmp r8d, 0
150 | je do_xor_avx2_end
151 |
152 | mov al, [rcx]
153 | mov r9b, [rdx]
154 | xor al, r9b
155 | mov [rcx], al
156 |
157 | inc rcx
158 | inc rdx
159 | dec r8d
160 |
161 | jmp stragglers3
162 |
163 | do_xor_avx2_end:
164 | ret
165 |
166 | #else
167 |
168 | .global _do_xor_sse2@12
169 |
170 | /* void __stdcall do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */
171 | _do_xor_sse2@12:
172 | /* edi = buf1
173 | * edx = buf2
174 | * esi = len
175 | * eax = tmp1
176 | * ecx = tmp2
177 | * xmm0 = tmp3
178 | * xmm1 = tmp4 */
179 |
180 | push ebp
181 | mov ebp, esp
182 |
183 | push esi
184 | push edi
185 |
186 | mov edi, [ebp+8]
187 | mov edx, [ebp+12]
188 | mov esi, [ebp+16]
189 |
190 | mov eax, edi
191 | and eax, 15
192 | cmp eax, 0
193 | jne stragglers2
194 |
195 | mov eax, edx
196 | and eax, 15
197 | cmp eax, 0
198 | jne stragglers2
199 |
200 | do_xor_sse2_loop:
201 | cmp esi, 16
202 | jl stragglers2
203 |
204 | movdqa xmm0, [edi]
205 | movdqa xmm1, [edx]
206 | pxor xmm0, xmm1
207 | movdqa [edi], xmm0
208 |
209 | add edi, 16
210 | add edx, 16
211 | sub esi, 16
212 |
213 | jmp do_xor_sse2_loop
214 |
215 | stragglers2:
216 |
217 | cmp esi, 4
218 | jl stragglers
219 |
220 | mov eax, [edi]
221 | mov ecx, [edx]
222 | xor eax, ecx
223 | mov [edi], eax
224 |
225 | add edi, 4
226 | add edx, 4
227 | sub esi, 4
228 |
229 | jmp stragglers2
230 |
231 | stragglers:
232 |
233 | cmp esi, 0
234 | je do_xor_sse2_end
235 |
236 | mov al, [edi]
237 | mov cl, [edx]
238 | xor al, cl
239 | mov [edi], al
240 |
241 | inc edi
242 | inc edx
243 | dec esi
244 |
245 | jmp stragglers
246 |
247 | do_xor_sse2_end:
248 | pop edi
249 | pop esi
250 | pop ebp
251 |
252 | ret 12
253 |
254 | .global _do_xor_avx2@12
255 |
256 | /* void __stdcall do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */
257 | _do_xor_avx2@12:
258 | /* edi = buf1
259 | * edx = buf2
260 | * esi = len
261 | * eax = tmp1
262 | * ecx = tmp2
263 | * xmm0 = tmp3
264 | * xmm1 = tmp4 */
265 |
266 | push ebp
267 | mov ebp, esp
268 |
269 | push esi
270 | push edi
271 |
272 | mov edi, [ebp+8]
273 | mov edx, [ebp+12]
274 | mov esi, [ebp+16]
275 |
276 | mov eax, edi
277 | and eax, 31
278 | cmp eax, 0
279 | jne stragglers4
280 |
281 | mov eax, edx
282 | and eax, 31
283 | cmp eax, 0
284 | jne stragglers4
285 |
286 | do_xor_avx2_loop:
287 | cmp esi, 32
288 | jl stragglers4
289 |
290 | vmovdqa ymm0, [edi]
291 | vmovdqa ymm1, [edx]
292 | vpxor ymm0, ymm0, ymm1
293 | vmovdqa [edi], ymm0
294 |
295 | add edi, 32
296 | add edx, 32
297 | sub esi, 32
298 |
299 | jmp do_xor_avx2_loop
300 |
301 | stragglers4:
302 |
303 | cmp esi, 4
304 | jl stragglers3
305 |
306 | mov eax, [edi]
307 | mov ecx, [edx]
308 | xor eax, ecx
309 | mov [edi], eax
310 |
311 | add edi, 4
312 | add edx, 4
313 | sub esi, 4
314 |
315 | jmp stragglers4
316 |
317 | stragglers3:
318 |
319 | cmp esi, 0
320 | je do_xor_avx2_end
321 |
322 | mov al, [edi]
323 | mov cl, [edx]
324 | xor al, cl
325 | mov [edi], al
326 |
327 | inc edi
328 | inc edx
329 | dec esi
330 |
331 | jmp stragglers3
332 |
333 | do_xor_avx2_end:
334 | pop edi
335 | pop esi
336 | pop ebp
337 |
338 | ret 12
339 |
340 | #endif
341 |
--------------------------------------------------------------------------------
/src/xor-masm.asm:
--------------------------------------------------------------------------------
1 | ; Copyright (c) Mark Harmstone 2020
2 | ;
3 | ; This file is part of WinBtrfs.
4 | ;
5 | ; WinBtrfs is free software: you can redistribute it and/or modify
6 | ; it under the terms of the GNU Lesser General Public Licence as published by
7 | ; the Free Software Foundation, either version 3 of the Licence, or
8 | ; (at your option) any later version.
9 | ;
10 | ; WinBtrfs is distributed in the hope that it will be useful,
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ; GNU Lesser General Public Licence for more details.
14 | ;
15 | ; You should have received a copy of the GNU Lesser General Public Licence
16 | ; along with WinBtrfs. If not, see .
17 |
18 | IFDEF RAX
19 | ELSE
20 | .686P
21 | .xmm
22 | ENDIF
23 |
24 | _TEXT SEGMENT
25 |
26 | IFDEF RAX
27 |
28 | PUBLIC do_xor_sse2
29 |
30 | ; void do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len);
31 | do_xor_sse2:
32 | ; rcx = buf1
33 | ; rdx = buf2
34 | ; r8d = len
35 | ; rax = tmp1
36 | ; r9 = tmp2
37 | ; xmm0 = tmp3
38 | ; xmm1 = tmp4
39 |
40 | mov rax, rcx
41 | and rax, 15
42 | cmp rax, 0
43 | jne stragglers2
44 |
45 | mov rax, rdx
46 | and rax, 15
47 | cmp rax, 0
48 | jne stragglers2
49 |
50 | do_xor_sse2_loop:
51 | cmp r8d, 16
52 | jl stragglers2
53 |
54 | movdqa xmm0, [rcx]
55 | movdqa xmm1, [rdx]
56 | pxor xmm0, xmm1
57 | movdqa [rcx], xmm0
58 |
59 | add rcx, 16
60 | add rdx, 16
61 | sub r8d, 16
62 |
63 | jmp do_xor_sse2_loop
64 |
65 | stragglers2:
66 |
67 | cmp r8d, 8
68 | jl stragglers
69 |
70 | mov rax, [rcx]
71 | mov r9, [rdx]
72 | xor rax, r9
73 | mov [rcx], rax
74 |
75 | add rcx, 8
76 | add rdx, 8
77 | sub r8d, 8
78 |
79 | jmp stragglers2
80 |
81 | stragglers:
82 |
83 | cmp r8d, 0
84 | je do_xor_sse2_end
85 |
86 | mov al, [rcx]
87 | mov r9b, [rdx]
88 | xor al, r9b
89 | mov [rcx], al
90 |
91 | inc rcx
92 | inc rdx
93 | dec r8d
94 |
95 | jmp stragglers
96 |
97 | do_xor_sse2_end:
98 | ret
99 |
100 | PUBLIC do_xor_avx2
101 |
102 | ; void do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len);
103 | do_xor_avx2:
104 | ; rcx = buf1
105 | ; rdx = buf2
106 | ; r8d = len
107 | ; rax = tmp1
108 | ; r9 = tmp2
109 | ; xmm0 = tmp3
110 | ; xmm1 = tmp4
111 |
112 | mov rax, rcx
113 | and rax, 31
114 | cmp rax, 0
115 | jne stragglers4
116 |
117 | mov rax, rdx
118 | and rax, 31
119 | cmp rax, 0
120 | jne stragglers4
121 |
122 | do_xor_avx2_loop:
123 | cmp r8d, 32
124 | jl stragglers4
125 |
126 | vmovdqa ymm0, YMMWORD PTR[rcx]
127 | vmovdqa ymm1, YMMWORD PTR[rdx]
128 | vpxor ymm0, ymm0, ymm1
129 | vmovdqa YMMWORD PTR[rcx], ymm0
130 |
131 | add rcx, 32
132 | add rdx, 32
133 | sub r8d, 32
134 |
135 | jmp do_xor_avx2_loop
136 |
137 | stragglers4:
138 |
139 | cmp r8d, 8
140 | jl stragglers3
141 |
142 | mov rax, [rcx]
143 | mov r9, [rdx]
144 | xor rax, r9
145 | mov [rcx], rax
146 |
147 | add rcx, 8
148 | add rdx, 8
149 | sub r8d, 8
150 |
151 | jmp stragglers4
152 |
153 | stragglers3:
154 |
155 | cmp r8d, 0
156 | je do_xor_avx2_end
157 |
158 | mov al, [rcx]
159 | mov r9b, [rdx]
160 | xor al, r9b
161 | mov [rcx], al
162 |
163 | inc rcx
164 | inc rdx
165 | dec r8d
166 |
167 | jmp stragglers3
168 |
169 | do_xor_avx2_end:
170 | ret
171 |
172 | ELSE
173 |
174 | PUBLIC do_xor_sse2@12
175 |
176 | ; void __stdcall do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len);
177 | do_xor_sse2@12:
178 | ; edi = buf1
179 | ; edx = buf2
180 | ; esi = len
181 | ; eax = tmp1
182 | ; ecx = tmp2
183 | ; xmm0 = tmp3
184 | ; xmm1 = tmp4
185 |
186 | push ebp
187 | mov ebp, esp
188 |
189 | push esi
190 | push edi
191 |
192 | mov edi, [ebp+8]
193 | mov edx, [ebp+12]
194 | mov esi, [ebp+16]
195 |
196 | mov eax, edi
197 | and eax, 15
198 | cmp eax, 0
199 | jne stragglers2
200 |
201 | mov eax, edx
202 | and eax, 15
203 | cmp eax, 0
204 | jne stragglers2
205 |
206 | do_xor_sse2_loop:
207 | cmp esi, 16
208 | jl stragglers2
209 |
210 | movdqa xmm0, [edi]
211 | movdqa xmm1, [edx]
212 | pxor xmm0, xmm1
213 | movdqa [edi], xmm0
214 |
215 | add edi, 16
216 | add edx, 16
217 | sub esi, 16
218 |
219 | jmp do_xor_sse2_loop
220 |
221 | stragglers2:
222 |
223 | cmp esi, 4
224 | jl stragglers
225 |
226 | mov eax, [edi]
227 | mov ecx, [edx]
228 | xor eax, ecx
229 | mov [edi], eax
230 |
231 | add edi, 4
232 | add edx, 4
233 | sub esi, 4
234 |
235 | jmp stragglers2
236 |
237 | stragglers:
238 |
239 | cmp esi, 0
240 | je do_xor_sse2_end
241 |
242 | mov al, [edi]
243 | mov cl, [edx]
244 | xor al, cl
245 | mov [edi], al
246 |
247 | inc edi
248 | inc edx
249 | dec esi
250 |
251 | jmp stragglers
252 |
253 | do_xor_sse2_end:
254 | pop edi
255 | pop esi
256 | pop ebp
257 |
258 | ret 12
259 |
260 | PUBLIC do_xor_avx2@12
261 |
262 | ; void __stdcall do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len);
263 | do_xor_avx2@12:
264 | ; edi = buf1
265 | ; edx = buf2
266 | ; esi = len
267 | ; eax = tmp1
268 | ; ecx = tmp2
269 | ; xmm0 = tmp3
270 | ; xmm1 = tmp4
271 |
272 | push ebp
273 | mov ebp, esp
274 |
275 | push esi
276 | push edi
277 |
278 | mov edi, [ebp+8]
279 | mov edx, [ebp+12]
280 | mov esi, [ebp+16]
281 |
282 | mov eax, edi
283 | and eax, 31
284 | cmp eax, 0
285 | jne stragglers4
286 |
287 | mov eax, edx
288 | and eax, 31
289 | cmp eax, 0
290 | jne stragglers4
291 |
292 | do_xor_avx2_loop:
293 | cmp esi, 32
294 | jl stragglers4
295 |
296 | vmovdqa ymm0, YMMWORD PTR[edi]
297 | vmovdqa ymm1, YMMWORD PTR[edx]
298 | vpxor ymm0, ymm0, ymm1
299 | vmovdqa YMMWORD PTR[edi], ymm0
300 |
301 | add edi, 32
302 | add edx, 32
303 | sub esi, 32
304 |
305 | jmp do_xor_avx2_loop
306 |
307 | stragglers4:
308 |
309 | cmp esi, 4
310 | jl stragglers3
311 |
312 | mov eax, [edi]
313 | mov ecx, [edx]
314 | xor eax, ecx
315 | mov [edi], eax
316 |
317 | add edi, 4
318 | add edx, 4
319 | sub esi, 4
320 |
321 | jmp stragglers4
322 |
323 | stragglers3:
324 |
325 | cmp esi, 0
326 | je do_xor_avx2_end
327 |
328 | mov al, [edi]
329 | mov cl, [edx]
330 | xor al, cl
331 | mov [edi], al
332 |
333 | inc edi
334 | inc edx
335 | dec esi
336 |
337 | jmp stragglers3
338 |
339 | do_xor_avx2_end:
340 | pop edi
341 | pop esi
342 | pop ebp
343 |
344 | ret 12
345 |
346 | ENDIF
347 |
348 | _TEXT ENDS
349 |
350 | end
351 |
--------------------------------------------------------------------------------
/src/zstd-shim.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | static void* ZSTD_malloc(size_t size) {
5 | return NULL;
6 | }
7 |
8 | static void* ZSTD_calloc(size_t nmemb, size_t size) {
9 | return NULL;
10 | }
11 |
12 | static void ZSTD_free(void* ptr) {
13 | }
14 |
15 | #ifdef _MSC_VER
16 |
17 | #include
18 |
19 | #pragma intrinsic(_byteswap_uint64)
20 | #pragma intrinsic(_byteswap_ulong)
21 | #pragma intrinsic(_rotl)
22 | #pragma intrinsic(_rotl64)
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------