├── .clang-format ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── LICENSE ├── Makefile.frag ├── Makefile.frag.w32 ├── Readme.EN.md ├── Readme.md ├── config.m4 ├── config.w32 ├── patches ├── Readme.md ├── cli_checks_80.patch ├── cli_checks_81.patch ├── cli_checks_83.patch ├── cli_checks_84.patch ├── cli_static_80.patch ├── cli_static_84.patch ├── comctl32.patch ├── disable_huge_page_80.patch ├── disable_huge_page_84.patch ├── macos_iconv_80.patch ├── macos_iconv_81.patch ├── macos_iconv_82.patch ├── macos_iconv_83.patch ├── macos_iconv_84.patch ├── phar_80.patch ├── phar_81.patch ├── static_extensions_win32_80.patch ├── static_extensions_win32_83.patch ├── static_extensions_win32_84.patch ├── static_opcache_80.patch ├── static_opcache_81.patch ├── static_opcache_82.patch ├── static_opcache_83.patch ├── static_opcache_84.patch ├── vcruntime140_74.patch ├── vcruntime140_80.patch ├── win32_74.patch ├── win32_80.patch ├── win32_82.patch └── zend_stream.patch ├── php_micro.c ├── php_micro.h ├── php_micro.rc ├── php_micro_fileinfo.c ├── php_micro_fileinfo.h ├── php_micro_helper.c ├── php_micro_helper.h ├── php_micro_hooks.c ├── php_micro_hooks.h └── tests ├── .gitignore ├── Readme.md ├── fakecmd.php ├── micro ├── argvs.phpt ├── micro_open_self.phpt ├── micro_version.phpt ├── phar.phpt ├── php_binary.phpt ├── seek_self.inc └── seek_self.phpt └── simpleecho.php /.clang-format: -------------------------------------------------------------------------------- 1 | 2 | # clang-format config for clang-format 13 3 | 4 | Language: Cpp 5 | 6 | BasedOnStyle: LLVM 7 | UseTab: Never 8 | IndentWidth: 4 9 | TabWidth: 4 10 | 11 | BreakBeforeBraces: Custom 12 | BraceWrapping: 13 | AfterEnum: false 14 | AfterStruct: false 15 | AfterFunction: false 16 | BeforeElse: false 17 | AfterExternBlock: false 18 | SplitEmptyFunction: false 19 | AfterControlStatement: Never 20 | SplitEmptyRecord: false 21 | 22 | IndentPPDirectives: AfterHash 23 | IndentCaseLabels: true 24 | IndentGotoLabels: true 25 | IndentWrappedFunctionNames: true 26 | 27 | BinPackArguments: false 28 | InsertTrailingCommas: Wrapped 29 | 30 | AllowShortCaseLabelsOnASingleLine: false 31 | AllowShortIfStatementsOnASingleLine: false 32 | AllowShortFunctionsOnASingleLine: false 33 | AllowShortLoopsOnASingleLine: true 34 | AllowShortBlocksOnASingleLine: Empty 35 | ColumnLimit: 120 36 | 37 | SortIncludes: true 38 | AlignTrailingComments: true 39 | AlignConsecutiveMacros: Consecutive 40 | AlignEscapedNewlines: DontAlign 41 | AlignAfterOpenBracket: DontAlign 42 | AlignOperands: DontAlign 43 | 44 | MacroBlockBegin: "ZEND_.+_START|ZEND_HASH_REVERSE_FOREACH_PTR|HASH_REVERSE_FOREACH_PTR|ZEND_BEGIN_ARG_INFO$" 45 | MacroBlockEnd: "ZEND_.+_END|ZEND_HASH_FOREACH_END_DEL|ZEND_END_ARG_INFO$" 46 | TypenameMacros: 47 | - 'PHP_FE' 48 | WhitespaceSensitiveMacros: 49 | - 'STRINGIZE' 50 | - 'STRINGIZE2' 51 | 52 | IncludeBlocks: Preserve 53 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | fetchversion: 9 | name: Fetch latest PHP version 10 | runs-on: "ubuntu-latest" 11 | outputs: 12 | info: ${{ steps.fetch.outputs.info }} 13 | steps: 14 | - name: Fetch version info 15 | id: fetch 16 | run: | 17 | printf "info=" >> $GITHUB_OUTPUT 18 | jq -rcs ' 19 | # default targets 20 | [{ 21 | "name": "master", 22 | "rev":"master", 23 | "patch":"84", 24 | }] + 25 | [.[] | { 26 | # ver is like 8.0.0 27 | "ver" : . | keys | first 28 | } | { 29 | "name": .ver, 30 | "rev": ("php-"+.ver), 31 | "patch": { 32 | # mapping maj.min to patches used 33 | "8.4": "84", 34 | "8.3": "83", 35 | "8.2": "82", 36 | "8.1": "81", 37 | "8.0": "80", 38 | }[.ver | sub("(?\\d+\\.\\d+)\\..+"; .v)], 39 | }]' \ 40 | <(curl -sfSL 'https://www.php.net/releases/?json&max=1&version=8.0') \ 41 | <(curl -sfSL 'https://www.php.net/releases/?json&max=1&version=8.1') \ 42 | <(curl -sfSL 'https://www.php.net/releases/?json&max=1&version=8.2') \ 43 | <(curl -sfSL 'https://www.php.net/releases/?json&max=1&version=8.3') >> $GITHUB_OUTPUT 44 | wintests: 45 | name: Windows tests for PHP ${{ matrix.name }} 46 | runs-on: "windows-latest" 47 | needs: 48 | - fetchversion 49 | strategy: 50 | matrix: 51 | include: ${{ fromJSON(needs.fetchversion.outputs.info) }} 52 | max-parallel: 3 53 | fail-fast: false 54 | steps: 55 | - name: Disable autocrlf 56 | run: | 57 | git config --global core.autocrlf false 58 | git config --global core.eol lf 59 | 60 | - name: Checkout PHP 61 | uses: actions/checkout@v4 62 | with: 63 | repository: php/php-src 64 | path: php-src 65 | ref: ${{ matrix.rev }} 66 | 67 | - name: Checkout micro 68 | uses: actions/checkout@v4 69 | with: 70 | path: php-src/sapi/micro 71 | 72 | - name: Checkout php-sdk-binary-tools 73 | uses: actions/checkout@v4 74 | with: 75 | repository: php/php-sdk-binary-tools 76 | path: php-sdk-binary-tools 77 | ref: master 78 | 79 | - name: Apply patches 80 | shell: powershell 81 | working-directory: php-src 82 | run: | 83 | $patchVer = "${{ matrix.patch }}" 84 | $series = '84', '83', '82', '81', '80' 85 | $patches = 'cli_checks', 'vcruntime140', 'win32', 'zend_stream', 'phar', 'comctl32', 'static_opcache', 'static_extensions_win32' 86 | foreach ( $patch in $patches ) 87 | { 88 | $path = "sapi/micro/patches/${patch}.patch" 89 | if (Test-Path $path -PathType Leaf) { 90 | Write-Host "Applying $path" 91 | Get-Content $path | patch -p1 92 | continue 93 | } 94 | foreach ( $ver in $series ) { 95 | if ( $patchVer -lt $ver ) { 96 | continue 97 | } 98 | $path = "sapi/micro/patches/${patch}_$ver.patch" 99 | if (Test-Path $path -PathType Leaf) { 100 | Write-Host "Applying $path" 101 | Get-Content $path | patch -p1 102 | break 103 | } 104 | } 105 | } 106 | 107 | - name: Build micro SAPI for PHP 108 | shell: cmd /c ..\php-sdk-binary-tools\phpsdk-vs17-x64.bat -t {0} 109 | working-directory: php-src 110 | run: | 111 | buildconf && ^ 112 | configure ^ 113 | --disable-all ^ 114 | --enable-micro ^ 115 | --disable-zts ^ 116 | --enable-opcache ^ 117 | --enable-ctype ^ 118 | --enable-filter ^ 119 | --enable-mbstring ^ 120 | --enable-session ^ 121 | --enable-tokenizer ^ 122 | --enable-phar && ^ 123 | nmake micro 124 | 125 | - name: Upload built micro as artifact 126 | uses: actions/upload-artifact@v4 127 | with: 128 | name: micro_windows_${{ matrix.name }} 129 | path: php-src/x64/Release/micro.sfx 130 | if-no-files-found: error 131 | 132 | - name: Test micro SAPI for PHP 133 | shell: cmd /c ..\php-sdk-binary-tools\phpsdk-vs17-x64.bat -t {0} 134 | working-directory: php-src 135 | run: | 136 | nmake micro_test TESTS="--show-diff --color sapi/micro/tests" 137 | linuxtests: 138 | name: Linux tests for PHP ${{ matrix.name }} 139 | runs-on: "ubuntu-latest" 140 | needs: 141 | - fetchversion 142 | strategy: 143 | matrix: 144 | include: ${{ fromJSON(needs.fetchversion.outputs.info) }} 145 | max-parallel: 3 146 | fail-fast: false 147 | steps: 148 | - name: Checkout PHP 149 | uses: actions/checkout@v4 150 | with: 151 | repository: php/php-src 152 | path: php-src 153 | ref: ${{ matrix.rev }} 154 | 155 | - name: Checkout micro 156 | uses: actions/checkout@v4 157 | with: 158 | path: php-src/sapi/micro 159 | 160 | - name: Apply patches 161 | shell: bash 162 | working-directory: php-src 163 | run: | 164 | patchVer="${{ matrix.patch }}" 165 | for patch in 'cli_checks' 'disable_huge_page' 'phar' 'static_opcache' 166 | do 167 | path="sapi/micro/patches/${patch}.patch" 168 | if [ -f $path ] 169 | then 170 | echo "Applying $path" 171 | patch -p1 < $path 172 | continue 173 | fi 174 | for ver in '84' '83' '82' '81' '80' 175 | do 176 | if [ $patchVer -lt $ver ] 177 | then 178 | continue 179 | fi 180 | path="sapi/micro/patches/${patch}_${ver}.patch" 181 | if [ -f $path ] 182 | then 183 | echo "Applying $path" 184 | patch -p1 < $path 185 | break 186 | fi 187 | done 188 | done 189 | 190 | - name: Install deps 191 | run: | 192 | sudo apt-get update && 193 | sudo apt-get install -yyq re2c 194 | 195 | - name: Build micro SAPI for PHP 196 | working-directory: php-src 197 | run: | 198 | ./buildconf --force && 199 | ./configure \ 200 | --disable-all \ 201 | --disable-cgi \ 202 | --disable-cli \ 203 | --enable-micro \ 204 | --disable-phpdbg \ 205 | --enable-opcache \ 206 | --without-pear \ 207 | --disable-shared \ 208 | --enable-static \ 209 | --disable-dom \ 210 | --disable-simplexml \ 211 | --disable-xml \ 212 | --disable-xmlreader \ 213 | --disable-xmlwriter \ 214 | --enable-ctype \ 215 | --enable-filter \ 216 | --enable-mbstring \ 217 | --enable-session \ 218 | --enable-sockets \ 219 | --enable-tokenizer \ 220 | --enable-phar \ 221 | --enable-posix \ 222 | --enable-pcntl \ 223 | --disable-mbregex && 224 | make -j `nproc` \ 225 | EXTRA_CFLAGS='-Os' \ 226 | EXTRA_LDFLAGS_PROGRAM=-lpthread && 227 | elfedit --output-osabi linux sapi/micro/micro.sfx 228 | 229 | - name: Upload built micro as artifact 230 | uses: actions/upload-artifact@v4 231 | with: 232 | name: micro_linux_${{ matrix.name }} 233 | path: php-src/sapi/micro/micro.sfx 234 | if-no-files-found: error 235 | 236 | - name: Test micro SAPI for PHP 237 | working-directory: php-src 238 | run: | 239 | make micro_test TESTS="--show-diff --color sapi/micro/tests" 240 | macostests: 241 | name: macOS tests for PHP ${{ matrix.name }} 242 | #runs-on: "macos-latest" 243 | # macos-14-arm64 now cannot build php without install many things 244 | # we cannot select macos-14 because macos-14 will select arm64 245 | runs-on: "macos-13" 246 | needs: 247 | - fetchversion 248 | strategy: 249 | matrix: 250 | include: ${{ fromJSON(needs.fetchversion.outputs.info) }} 251 | max-parallel: 3 252 | fail-fast: false 253 | steps: 254 | - name: Checkout PHP 255 | uses: actions/checkout@v4 256 | with: 257 | repository: php/php-src 258 | path: php-src 259 | ref: ${{ matrix.rev }} 260 | 261 | - name: Checkout micro 262 | uses: actions/checkout@v4 263 | with: 264 | path: php-src/sapi/micro 265 | 266 | - name: Apply patches 267 | shell: bash 268 | working-directory: php-src 269 | run: | 270 | patchVer="${{ matrix.patch }}" 271 | for patch in 'cli_checks' 'disable_huge_page' 'phar' 'static_opcache' 272 | do 273 | path="sapi/micro/patches/${patch}.patch" 274 | if [ -f $path ] 275 | then 276 | echo "Applying $path" 277 | patch -p1 < $path 278 | continue 279 | fi 280 | for ver in '84' '83' '82' '81' '80' 281 | do 282 | if [ $patchVer -lt $ver ] 283 | then 284 | continue 285 | fi 286 | path="sapi/micro/patches/${patch}_${ver}.patch" 287 | if [ -f $path ] 288 | then 289 | echo "Applying $path" 290 | patch -p1 < $path 291 | break 292 | fi 293 | done 294 | done 295 | 296 | - name: Install deps 297 | run: | 298 | brew install bison re2c 299 | 300 | - name: Build micro SAPI for PHP 301 | working-directory: php-src 302 | run: | 303 | export PATH="/usr/local/opt/bison/bin:$PATH" 304 | ./buildconf --force && 305 | ./configure \ 306 | --disable-all \ 307 | --disable-cgi \ 308 | --disable-cli \ 309 | --enable-micro \ 310 | --disable-phpdbg \ 311 | --without-pear \ 312 | --enable-opcache \ 313 | --disable-shared \ 314 | --enable-static \ 315 | --disable-dom \ 316 | --disable-simplexml \ 317 | --disable-xml \ 318 | --disable-xmlreader \ 319 | --disable-xmlwriter \ 320 | --enable-ctype \ 321 | --enable-filter \ 322 | --enable-mbstring \ 323 | --enable-session \ 324 | --enable-sockets \ 325 | --enable-tokenizer \ 326 | --enable-phar \ 327 | --enable-posix \ 328 | --enable-pcntl \ 329 | --disable-mbregex && 330 | make -j `sysctl -n hw.logicalcpu` \ 331 | EXTRA_CFLAGS='-Os' 332 | 333 | - name: Upload built micro as artifact 334 | uses: actions/upload-artifact@v4 335 | with: 336 | name: micro_macos_${{ matrix.name }} 337 | path: php-src/sapi/micro/micro.sfx 338 | if-no-files-found: error 339 | 340 | - name: Test micro SAPI for PHP 341 | working-directory: php-src 342 | run: | 343 | make micro_test TESTS="--show-diff --color sapi/micro/tests" 344 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.lo 3 | *.a 4 | *.la 5 | *.obj 6 | *.sfx 7 | *.sfx.dwarf 8 | *.dep 9 | *.debug 10 | *.bin 11 | .libs 12 | 13 | .vs 14 | .vscode 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | 2 | micro: $(SAPI_MICRO_PATH) 3 | 4 | $(SAPI_MICRO_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_MICRO_OBJS) 5 | $(BUILD_MICRO) 6 | 7 | MICRO_EXES = sapi/micro/tests/simpleecho.exe sapi/micro/tests/fakecmd.exe 8 | 9 | $(MICRO_EXES): $(SAPI_MICRO_PATH) 10 | @binname=$@;\ 11 | cat $(SAPI_MICRO_PATH) $${binname%.exe}.php > $@ || {\ 12 | rm $@; \ 13 | exit 1; \ 14 | } 15 | @chmod 0755 $@ 16 | 17 | MICRO_FAKECMD=sapi/micro/tests/fakecmd.exe 18 | 19 | micro_test: $(SAPI_MICRO_PATH) $(MICRO_EXES) 20 | @[ x"hello world" = "x`sapi/micro/tests/simpleecho.exe nonce world`" ] || {\ 21 | echo sanity check for micro.sfx failed, the sfx generated may be corrupt. >&2 ;\ 22 | exit 1;\ 23 | } 24 | @SKIP_IO_CAPTURE_TESTS=yes \ 25 | TEST_PHP_EXECUTABLE=$(MICRO_FAKECMD) \ 26 | TEST_PHP_SRCDIR=$(top_srcdir) \ 27 | CC="$(CC)" \ 28 | $(MICRO_FAKECMD) -n $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n $(TESTS); \ 29 | exit $$?; 30 | -------------------------------------------------------------------------------- /Makefile.frag.w32: -------------------------------------------------------------------------------- 1 | 2 | say_warning: 3 | @echo php build system do not support statically build in win32. 4 | @echo try `nmake micro`. 5 | 6 | MICRO_SFX = "$(BUILD_DIR)\micro.sfx" 7 | MICRO_EXES = "$(BUILD_DIR)\sapi\micro\tests\simpleecho.exe" "$(BUILD_DIR)\sapi\micro\tests\fakecmd.exe" 8 | 9 | _MICRO_RES_BUILD = $(RC) /nologo /n /fo $(BUILD_DIR)\sapi\micro\micro.exe.res \ 10 | /d WANT_LOGO \ 11 | /d APP_LOGO="\"$(APP_LOGO)\"" \ 12 | /d FILE_DESCRIPTION="\"micro.exe\"" \ 13 | /d FILE_NAME="\"micro.exe\"" \ 14 | /d PRODUCT_NAME="\"PHP Script Interpreter\"" \ 15 | /d URL="\"http://www.php.net\"" \ 16 | /d INTERNAL_NAME="\"MICRO SAPI\"" \ 17 | /d THANKS_GUYS="\"\"" \ 18 | $(BASE_INCLUDES) /I$(BUILD_DIR) 19 | 20 | MICRO_LINKING_OBJS = $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(MICRO_GLOBAL_OBJS) 21 | MICRO_LINKING_OBJS_RESP = $(PHP_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(MICRO_GLOBAL_OBJS_RESP) 22 | 23 | _MICRO_LINKALL = @"$(LINK)" /nologo \ 24 | $(MICRO_LINKING_OBJS_RESP) \ 25 | $(ASM_OBJS) \ 26 | $(STATIC_EXT_LIBS) $(LIBS_MICRO) $(LIBS) \ 27 | $(BUILD_DIR)\sapi\micro\micro.exe.res \ 28 | /out:$(MICRO_SFX) $(LDFLAGS) $(LDFLAGS_MICRO) 29 | 30 | _MICRO_MT = if $(MT) neq "" if exist $(BUILD_DIR)\micro.exe.manifest $(MT) -nologo -manifest $(BUILD_DIR)\micro.exe.manifest -outputresource:$(MICRO_SFX);1 31 | 32 | # for 2-step generation 33 | $(MICRO_SFX): generated_files $(MICRO_LINKING_OBJS) $(BUILD_DIR)\micro.exe.manifest 34 | @echo Prebuilding 35 | $(_MICRO_RES_BUILD) sapi\micro\php_micro.rc 36 | @$(_MICRO_LINKALL) 37 | @$(_MICRO_MT) 38 | 39 | $(MICRO_EXES): $(MICRO_SFX) 40 | @if not exist "$(BUILD_DIR)\sapi\micro\tests" @mkdir $(BUILD_DIR)\sapi\micro\tests 41 | @for %I in ($@) do copy /b $(MICRO_SFX) + sapi\micro\tests\%~nI.php %I 42 | 43 | micro: $(MICRO_SFX) 44 | @echo Done build micro sfx 45 | 46 | micro_test: set-tmp-env $(MICRO_SFX) $(MICRO_EXES) 47 | @for /f "tokens=* usebackq" %F IN (`"$(BUILD_DIR)\sapi\micro\tests\simpleecho.exe" nonce world`) do @if not "%F" == "hello world" @echo sanity check for micro.sfx failed, the sfx generated may be corrupt. 48 | @"$(BUILD_DIR)\sapi\micro\tests\fakecmd.exe" -n -d open_basedir= -d output_buffering=0 -d memory_limit=-1 run-tests.php -p "$(BUILD_DIR)\sapi\micro\tests\fakecmd.exe" -n $(TESTS) 49 | -------------------------------------------------------------------------------- /Readme.EN.md: -------------------------------------------------------------------------------- 1 | # micro self-executable SAPI for PHP 2 | 3 | [![Chinese readme](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87%20%F0%9F%87%A8%F0%9F%87%B3-white)](Readme.md) 4 | ![php](https://img.shields.io/badge/php-8.0--8.2-royalblue.svg) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 6 | [![tests](https://github.com/dixyes/phpmicro/actions/workflows/tests.yml/badge.svg)](https://github.com/dixyes/phpmicro/actions/workflows/tests.yml) 7 | 8 | micro self-executable SAPI makes PHP self-executable. 9 | 10 | Just concatenate micro.sfx and a random PHP source file or PHAR into a single file to use it. 11 | 12 | ## Compatibility 13 | 14 | Currently, it only supports PHP8+ on Windows, Linux, and macOS (and maybe some BSDs). 15 | 16 | ## Fetch and Usage 17 | 18 | A micro `micro.sfx` binary containing the minimal extensions set is built automatically in [Github Actions](actions). If you need more extensions, build your own micro or use [crazywhalecc/static-php-cli](https://github.com/crazywhalecc/static-php-cli) (swoole/swow/libevent) or grab one in [lwmbs actions](https://github.com/dixyes/lwmbs/actions)(swow) 19 | 20 | To use it, simply concatenate the `micro.sfx` file and any PHP source. 21 | 22 | For example: if the content of myawesomeapp.php is 23 | 24 | ```php 25 | myawesomeapp 41 | chmod 0755 ./myawesomeapp 42 | ./myawesomeapp 43 | # shows "hello, this is my awesome app." 44 | ``` 45 | 46 | or Windows: 47 | 48 | ```batch 49 | COPY /b \path\to\micro.sfx + myawesomeapp.php myawesomeapp.exe 50 | myawesomeapp.exe 51 | REM shows "hello, this is my awesome app." 52 | ``` 53 | 54 | ## Build micro.sfx 55 | 56 | ### Preparation 57 | 58 | 1.Clone this repository into `sapi/micro` under the PHP source directory 59 | 60 | ```bash 61 | # prepare PHP source 62 | git clone --branch 'PHP-choose-a-release' https://github.com/php/php-src/ php-src 63 | cd php-src 64 | # at PHP source dir 65 | git clone sapi/micro 66 | ``` 67 | 68 | 2.Apply patches 69 | 70 | Patches are placed in the "patches" directory. Choose patch(es) as you like, see [Readme.md](patches/Readme.md) in the patches dir for detail 71 | 72 | Apply a patch: 73 | 74 | ```bash 75 | # at PHP source dir 76 | patch -p1 < sapi/micro/patches/ 77 | ``` 78 | 79 | ### UNIX-like Build 80 | 81 | 0.Prepare the build environment according to [the official PHP documents](https://www.php.net/manual/en/install.unix.php). 82 | 83 | 1.buildconf 84 | 85 | ```bash 86 | # at PHP source dir 87 | ./buildconf --force 88 | ``` 89 | 90 | 2.configure 91 | 92 | ```bash 93 | # at PHP source dir 94 | ./configure 95 | ``` 96 | 97 | Options for reference: 98 | 99 | `--disable-phpdbg --disable-cgi --disable-cli --disable-all --enable-micro --enable-phar --with-ffi --enable-zlib` 100 | 101 | On Linux, libc compatibility can be a problem. To address this, micro provides two kinds of `configure` arguments: 102 | 103 | - `--enable-micro=yes`or`--enable-micro`: this will make PIE shared ELF micro sfx, this kind of binary cannot be invoked cross libc (i.e. you cannot run such a binary which was built on alpine with musl on any glibc-based CentOS), but the binary can do ffi and PHP `dl()` function. 104 | - `--enable-micro=all-static`: this will make full static ELF micro sfx, this kind of binary can even run barely on top of any linux kernel, but ffi/`dl()` is not supported. 105 | 106 | 3.make 107 | 108 | ```bash 109 | # at PHP source dir 110 | make micro 111 | ``` 112 | 113 | (`make all`(aka. `make`) may work also, but it is recommended to only build the micro SAPI.) 114 | 115 | The built file will be located at sapi/micro/micro.sfx. 116 | 117 | ### Windows Build 118 | 119 | 0.Prepare the build environment according to [the official PHP documents](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2), you may also try [my scripts](https://github.com/dixyes/php-dev-windows-tool) 120 | 121 | 1.buildconf 122 | 123 | ```batch 124 | # at PHP source dir 125 | buildconf 126 | ``` 127 | 128 | 2.configure 129 | 130 | ```batch 131 | # at PHP source dir 132 | configure 133 | ``` 134 | 135 | Options for reference: 136 | 137 | `--disable-all --disable-zts --enable-micro --enable-phar --with-ffi --enable-zlib` 138 | 139 | 3.make 140 | Due to the PHP build system's inability to statically build PHP binaries on Windows, you cannot build micro with `nmake` command. 141 | 142 | ```batch 143 | # at PHP source dir 144 | nmake micro 145 | ``` 146 | 147 | That built file is at `\\\\micro.sfx`. 148 | 149 | ## Optimizations 150 | 151 | The Hugepages optimization for Linux in the PHP build system results in a large sfx size. If you do not take advantage of Hugepages, use `disable_huge_page.patch` to reduce the sfx size. 152 | 153 | A static build under Linux requires libc. The most common libc, glibc, may be large, so musl is recommended instead. Manually installed musl or some distros provided musl will provide `musl-gcc` or `musl-clang` wrapper, use one of them before configure by specify CC/CXX environs, for example 154 | 155 | ```bash 156 | # ./buildconf things... 157 | export CC=musl-gcc 158 | export CXX=musl-gcc 159 | # ./configure things 160 | # make things 161 | ``` 162 | 163 | We aim to have all dependencies statically linked into sfx. However, some distro does not provide static versions of them. We may manually build them. 164 | 165 | libffi for example (note that the ffi extension is not supported in `all-static` builds): 166 | 167 | ```bash 168 | # fetch sources througe git 169 | git clone https://github.com/libffi/libffi 170 | cd libffi 171 | git checkout 172 | autoreconf -i 173 | # or download tarball 174 | wget 175 | tar xf 176 | cd 177 | # if we use musl 178 | export CC=musl-gcc 179 | export CXX=musl-gcc 180 | # build, install it 181 | ./configure --prefix=/my/prefered/path && 182 | make -j`nproc` && 183 | make install 184 | ``` 185 | 186 | then build micro as 187 | 188 | ```bash 189 | # ./buildconf things... 190 | # export CC=musl-xxx things... 191 | export PKG_CONFIG_PATH=/my/prefered/path/lib/pkgconfig 192 | # ./configure things 193 | # make things 194 | ``` 195 | 196 | ## Some details 197 | 198 | ### INI settings 199 | 200 | See wiki:[INI-settings](https://github.com/easysoft/phpmicro/wiki/INI-settings)(TODO: en version) 201 | 202 | ### PHP_BINARY constant 203 | 204 | In micro, the `PHP_BINARY` constant is an empty string. You can modify it using an ini setting: `micro.php_binary=somestring` 205 | 206 | ## OSS License 207 | 208 | ```plain 209 | Copyright 2020 Longyan 210 | 211 | Licensed under the Apache License, Version 2.0 (the "License"); 212 | you may not use this file except in compliance with the License. 213 | You may obtain a copy of the License at 214 | 215 | http://www.apache.org/licenses/LICENSE-2.0 216 | 217 | Unless required by applicable law or agreed to in writing, software 218 | distributed under the License is distributed on an "AS IS" BASIS, 219 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 220 | See the License for the specific language governing permissions and 221 | limitations under the License. 222 | ``` 223 | 224 | ## remind me to update the English readme and fix typos and strange or offensive expressions 225 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # micro 自执行SAPI 2 | 3 | [![English readme](https://img.shields.io/badge/README-English%20%F0%9F%87%AC%F0%9F%87%A7-white)](Readme.EN.md) 4 | ![php](https://img.shields.io/badge/php-8.0--8.2-royalblue.svg) 5 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 6 | [![tests](https://github.com/dixyes/phpmicro/actions/workflows/tests.yml/badge.svg)](https://github.com/dixyes/phpmicro/actions/workflows/tests.yml) 7 | 8 | micro自执行SAPI提供了php“自执行文件”的可能性 9 | 10 | 你只需要将构建的micro.sfx文件与任意php文件或者phar包拼接(`cat`或者`copy /b`)为一个文件就可以直接执行这个php文件 11 | 12 | ## 兼容性 13 | 14 | 目前兼容PHP8+;兼容Windows、Linux、macOS (可能也支持一些BSDs)。 15 | 16 | ## 获取与使用 17 | 18 | Github actions中构建了一个很少扩展的最小micro,如果需要扩展,请自行构建,参考下方构建说明或使用[crazywhalecc/static-php-cli](https://github.com/crazywhalecc/static-php-cli)(swow/swoole/libevent)从[lwmbs的workflow](https://github.com/dixyes/lwmbs/actions)(swow)下一个 19 | 20 | 将micro.sfx和php文件拼接即可使用 21 | 22 | 例如:myawesomeapp.php内容为 23 | 24 | ```php 25 | myawesomeapp 41 | chmod 0755 ./myawesomeapp 42 | ./myawesomeapp 43 | # 回显 "hello, this is my awesome app." 44 | ``` 45 | 46 | 或者Windows下 47 | 48 | ```batch 49 | COPY /b \path\to\micro.sfx + myawesomeapp.php myawesomeapp.exe 50 | myawesomeapp.exe 51 | REM 回显 "hello, this is my awesome app." 52 | ``` 53 | 54 | ## 构建 55 | 56 | ### 准备源码 57 | 58 | 1.将本仓库clone到php源码的sapi/micro下 59 | 60 | ```bash 61 | # 在php源码目录下 62 | git clone sapi/micro 63 | ``` 64 | 65 | 2.打patch 66 | 67 | patch文件在patches目录下,选择需要的patch文件,详细作用参考patches下的[Readme.md](patches/Readme.md) 68 | 69 | 并分别进行patch: 70 | 71 | ```bash 72 | # 在php源码目录下 73 | patch -p1 < sapi/micro/patches/ 74 | ``` 75 | 76 | ### unix-like 构建 77 | 78 | 0.参考官方构建说明准备PHP构建环境 79 | 80 | 1.buildconf 81 | 82 | ```bash 83 | # 在php源码目录下 84 | ./buildconf --force 85 | ``` 86 | 87 | 2.configure 88 | 89 | ```bash 90 | # 在php源码目录下 91 | ./configure 92 | ``` 93 | 94 | 参考的选项: 95 | 96 | `--disable-phpdbg --disable-cgi --disable-cli --disable-all --enable-micro --enable-phar --with-ffi --enable-zlib` 97 | 98 | Linux下,存在C库兼容性问题,对于这个,micro构建系统提供了两种选项: 99 | 100 | - `--enable-micro=yes`或者`--enable-micro`:这将会构建PIE的动态的micro,这种micro不能跨C库调用(即在alpine上构建的使用musl的micro不能在只安装了glibc的CentOS上使用,反过来也不能),但支持ffi和PHP的`dl()`函数。 101 | - `--enable-micro=all-static`:这将会构建静态的micro,这种micro不依赖C库,可以直接跑在支持的Linux内核上,但不能使用ffi/`dl()` 102 | 103 | 3.make 104 | 105 | ```bash 106 | # 在php源码目录下 107 | make micro 108 | ``` 109 | 110 | (`make all`(或者`make`) 或许也可以,但建议还是只构建micro SAPI 111 | 112 | 生成的文件在 sapi/micro/micro.sfx 113 | 114 | ### Windows 构建 115 | 116 | 0.参考[官方构建说明](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2)准备PHP构建环境,或者用[我的脚本](https://github.com/dixyes/php-dev-windows-tool)准备一下 117 | 118 | 1.buildconf 119 | 120 | ```batch 121 | # 在php源码目录下 122 | buildconf 123 | ``` 124 | 125 | 2.configure 126 | 127 | ```batch 128 | # 在php源码目录下 129 | configure 130 | ``` 131 | 132 | 参考的选项: 133 | 134 | `--disable-all --disable-zts --enable-micro --enable-phar --with-ffi --enable-zlib` 135 | 136 | 3.make 137 | 由于构建系统的实现问题, Windows下不能使用nmake命令直接构建,使用nmake micro来构建 138 | 139 | ```batch 140 | # 在php源码目录下 141 | nmake micro 142 | ``` 143 | 144 | 生成的文件在 `<架构名>\\<配置名>\\micro.sfx` 145 | 146 | ## 优化 147 | 148 | linux下php对于hugepages优化导致了生成的文件很大,如果不考虑对hugepages的优化,使用disable_huge_page.patch来来减小文件尺寸 149 | 150 | linux下静态构建需要包含c标准库,常见的glibc较大,推荐使用musl,手动安装的musl或者某些发行版会提供gcc(或clang)的musl wrapper:`musl-gcc`或者`musl-clang`。在进行configure之前,通过指定CC和CXX变量来使用这些wrapper 151 | 152 | 例如 153 | 154 | ```bash 155 | # ./buildconf things... 156 | export CC=musl-gcc 157 | export CXX=musl-gcc 158 | # ./configure balabala 159 | # make balabala 160 | ``` 161 | 162 | linux下构建时一般希望是纯静态的,但构建使用的发行版不一定提供依赖的库(zlib libffi等)的静态库版本,这时考虑自行构建依赖库 163 | 164 | 以libffi为例(`all-static`构建时不支持ffi): 165 | 166 | ```bash 167 | # 通过git获取源码 168 | git clone https://github.com/libffi/libffi 169 | cd libffi 170 | git checkout 171 | autoreconf -i 172 | # 或者直接下载tarball解压 173 | wget 174 | tar xf 175 | cd 176 | # 如果使用musl的话 177 | export CC=musl-gcc 178 | export CXX=musl-gcc 179 | # 构建安装 180 | ./configure --prefix=/my/prefered/path && 181 | make -j`nproc` && 182 | make install 183 | ``` 184 | 185 | 然后使用以下export命令来构建micro: 186 | 187 | ```bash 188 | # ./buildconf things... 189 | # export CC=musl-xxx things... 190 | export PKG_CONFIG_PATH=/my/prefered/path/lib/pkgconfig 191 | # ./configure balabala 192 | # make balabala 193 | ``` 194 | 195 | ## 一些细节 196 | 197 | ### INI配置 198 | 199 | 见wiki:[INI-settings](https://github.com/easysoft/phpmicro/wiki/INI-settings) 200 | 201 | ### PHP_BINARY常量 202 | 203 | micro中这个常量是空字符串,可以通过ini配置:`micro.php_binary=somestring` 204 | 205 | ## 开源许可 206 | 207 | ```plain 208 | Copyright 2020 Longyan 209 | 210 | Licensed under the Apache License, Version 2.0 (the "License"); 211 | you may not use this file except in compliance with the License. 212 | You may obtain a copy of the License at 213 | 214 | http://www.apache.org/licenses/LICENSE-2.0 215 | 216 | Unless required by applicable law or agreed to in writing, software 217 | distributed under the License is distributed on an "AS IS" BASIS, 218 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 219 | See the License for the specific language governing permissions and 220 | limitations under the License. 221 | ``` 222 | 223 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE([micro],, 2 | [AS_HELP_STRING([--enable-micro], 3 | [enable building micro PHP sfx ])], 4 | [no], 5 | [no]) 6 | 7 | dnl AC_CHECK_FUNCS(setproctitle) 8 | 9 | dnl AC_CHECK_HEADERS([sys/pstat.h]) 10 | 11 | dnl AC_CACHE_CHECK([for PS_STRINGS], [cli_cv_var_PS_STRINGS], 12 | dnl [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include 13 | dnl #include 14 | dnl ]], 15 | dnl [[PS_STRINGS->ps_nargvstr = 1; 16 | dnl PS_STRINGS->ps_argvstr = "foo";]])], 17 | dnl [cli_cv_var_PS_STRINGS=yes], 18 | dnl [cli_cv_var_PS_STRINGS=no])]) 19 | dnl if test "$cli_cv_var_PS_STRINGS" = yes ; then 20 | dnl AC_DEFINE([HAVE_PS_STRINGS], [], [Define to 1 if the PS_STRINGS thing exists.]) 21 | dnl fi 22 | 23 | AC_MSG_CHECKING(for micro build) 24 | if test "$PHP_MICRO" != "no"; then 25 | AC_MSG_RESULT(yes) 26 | 27 | PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/micro/Makefile.frag) 28 | 29 | dnl Set filename. 30 | SAPI_MICRO_PATH=sapi/micro/micro.sfx 31 | 32 | dnl Select SAPI. 33 | dnl CFLAGS="$CFLAGS -DPHP_MICRO_BUILD_SFX" 34 | PHP_SUBST(MICRO_CFLAGS) 35 | if test "x${enable_debug##yes}" != "x${enable_debug}"; then 36 | MICRO_CFLAGS=-D_DEBUG 37 | fi 38 | PHP_SELECT_SAPI(micro, program, php_micro.c php_micro_helper.c php_micro_hooks.c php_micro_fileinfo.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 \$(MICRO_CFLAGS), '$(SAPI_MICRO_PATH)') 39 | dnl add cli_???_process_title functions 40 | PHP_ADD_SOURCES_X(sapi/cli, php_cli_process_title.c ps_title.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_MICRO_OBJS) 41 | 42 | OVERALL_TARGET="$OVERALL_TARGETS \$(SAPI_MICRO_PATH) \$(MICRO_EXES)" 43 | 44 | MICRO_LIBS='$(EXTRA_LIBS)' 45 | case $host_alias in 46 | *aix*) 47 | AC_MSG_ERROR(not yet support aix) 48 | 49 | if test "$php_sapi_module" = "shared"; then 50 | BUILD_MICRO="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MICRO_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MICRO_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MICRO_PATH)" 51 | else 52 | BUILD_MICRO="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MICRO_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MICRO_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MICRO_PATH)" 53 | fi 54 | ;; 55 | *darwin*) 56 | if test "x${PHP_MICRO%%all-static*}" != "x${PHP_MICRO}"; then 57 | AC_MSG_WARN(macOS donot support static mach-o build) 58 | fi 59 | BUILD_MICRO="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_MICRO_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MICRO_PATH)" 60 | ;; 61 | *) 62 | if test "x${PHP_MICRO%%all-static*}" != "x${PHP_MICRO}"; then 63 | EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM -all-static" 64 | else 65 | dnl check if cc supports -static-libgcc 66 | AX_CHECK_COMPILE_FLAG([-static-libgcc], [ 67 | EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM -static-libgcc" 68 | ], []) 69 | dnl replace libresolv things with static versions 70 | MICRO_LIBS='$(EXTRA_LIBS:-lresolv=-Wl,-Bstatic,-lresolv,-Bdynamic)' 71 | fi 72 | PHP_SUBST(EXTRA_LDFLAGS) 73 | BUILD_MICRO="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MICRO_OBJS) ${MICRO_LIBS} \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MICRO_PATH)" 74 | ;; 75 | esac 76 | 77 | dnl Set executable for tests. 78 | dnl PHP_EXECUTABLE="\$(top_builddir)/\$(SAPI_CLI_PATH)" 79 | dnl PHP_SUBST(PHP_EXECUTABLE) 80 | 81 | dnl Expose to Makefile. 82 | PHP_SUBST(SAPI_MICRO_PATH) 83 | PHP_SUBST(BUILD_MICRO) 84 | 85 | dnl PHP_OUTPUT(sapi/cli/php.1) 86 | 87 | dnl PHP_INSTALL_HEADERS([sapi/cli/cli.h]) 88 | fi 89 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // vim:ft=javascript 2 | 3 | ARG_ENABLE('micro', 'Build micro PHP sfx', 'yes'); 4 | ARG_ENABLE('micro-win32', 'Build console-less micro PHP sfx', 'no'); 5 | ARG_ENABLE('micro-logo', 'Use custom logo for micro sfx', 'no'); 6 | 7 | // let us donot affect globals 8 | (function () { 9 | if (PHP_MICRO !== "yes") { 10 | return; 11 | } 12 | SAPI('micro', 'php_micro.c php_micro_fileinfo.c php_micro_helper.c php_micro_hooks.c', 'micro.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); 13 | // add cli_process_title sources 14 | ADD_SOURCES('sapi/cli', 'php_cli_process_title.c ps_title.c', 'micro'); 15 | 16 | ADD_FLAG('CFLAGS_MICRO_OBJ', '/TC /W3 /we4013 /wd4244 /wd4018'); 17 | 18 | ADD_FLAG("LIBS_MICRO", "ws2_32.lib"); 19 | ADD_FLAG("LIBS_MICRO", "shell32.lib"); 20 | 21 | ADD_FLAG("DEPS_MICRO", "say_warning error_out"); 22 | /* 23 | if (PHP_CRT_DEBUG == "yes") { 24 | ADD_FLAG("CFLAGS_MICRO", "/D PHP_WIN32_DEBUG_HEAP"); 25 | } 26 | */ 27 | if (PHP_MICRO_WIN32 == "yes") { 28 | ADD_FLAG("CFLAGS_MICRO", "/D PHP_MICRO_WIN32_NO_CONSOLE"); 29 | } 30 | 31 | if (PHP_MICRO_LOGO != "no") { 32 | ADD_FLAG("APP_LOGO", PHP_MICRO_LOGO); 33 | } else { 34 | ADD_FLAG("APP_LOGO", 'win32\\build\\php.ico'); 35 | } 36 | // for visual style 37 | ADD_FLAG('LDFLAGS_MICRO', "\"/manifestdependency:" + 38 | "type='win32' " + 39 | "name='Microsoft.Windows.Common-Controls' " + 40 | "version='6.0.0.0' " + 41 | "processorArchitecture='*' " + 42 | "publicKeyToken='6595b64144ccf1df' " + 43 | "language='*'\""); 44 | 45 | if (PHP_DEBUG != "no") { 46 | ADD_FLAG('LDFLAGS_MICRO', '/defaultlib:libcmtd'); 47 | } else { 48 | ADD_FLAG('LDFLAGS_MICRO', '/defaultlib:libcmt'); 49 | } 50 | 51 | ADD_FLAG("LDFLAGS_MICRO", "/stack:67108864"); 52 | ADD_FLAG('LDFLAGS_MICRO', '/nodefaultlib:MSVCRT'); 53 | ADD_FLAG('LDFLAGS_MICRO', '/nodefaultlib:MSVCRTD'); 54 | //ADD_FLAG('LDFLAGS_MICRO', '/nodefaultlib:LIBCMT'); 55 | ADD_FLAG('LDFLAGS_MICRO', '/ignore:4049'); 56 | 57 | if (PHP_FFI != 'no') { 58 | ADD_FLAG('LDFLAGS_MICRO', '/LTCG'); 59 | } 60 | 61 | ADD_MAKEFILE_FRAGMENT(); 62 | /* 63 | if (CHECK_LIB("edit_a.lib;edit.lib", "cli", PHP_CLI) && 64 | CHECK_HEADER_ADD_INCLUDE("editline/readline.h", "CFLAGS_CLI")) { 65 | ADD_FLAG("CFLAGS_CLI", "/D HAVE_LIBEDIT"); 66 | } 67 | */ 68 | 69 | if (PHP_VERSION >= 8) { 70 | if (PHP_MINOR_VERSION > 1) { 71 | // since 8.2, there was ASM_OBJS variable 72 | ADD_FLAG('MICRO_GLOBAL_OBJS', '$(ASM_OBJS)'); 73 | } else if (PHP_MINOR_VERSION == 1) { 74 | ADD_FLAG('MICRO_GLOBAL_OBJS', '$(BUILD_DIR)\\Zend\\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.obj $(BUILD_DIR)\\Zend\\make_$(FIBER_ASM_ARCH)_ms_pe_masm.obj'); 75 | } 76 | } 77 | 78 | })(); 79 | -------------------------------------------------------------------------------- /patches/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # 补丁 / Patches 3 | 4 | 名称 Name | 平台 Platform | 可选? Optional? | 用途 Usage 5 | --- | --- | --- | --- 6 | phar | * | 可选 Optional | 允许micro使用压缩phar Allow micro use compressed phar 7 | static_opcache | * | 可选 Optional | 支持静态构建opcache Support build opcache statically 8 | macos_iconv | macOS | 可选 Optional | 支持链接到系统的iconv Support link against system iconv 9 | static_extensions_win32 | Windows | 可选 Optional | 支持静态构建Windows其他扩展 Support build other extensions for windows 10 | cli_checks | * | 可选 Optional | 修改PHP内核中硬编码的SAPI检查 Modify hardcoden SAPI name checks in PHP core 11 | disable_huge_page | Linux | 可选 Optional | 禁用linux构建的max-page-size选项,缩减sfx体积(典型的, 10M+ -> 5M) Disable max-page-size for linux build,shrink sfx size (10M+ -> 5M typ.) 12 | vcruntime140 | Windows | 必须 Nessesary | 禁用sfx启动时GetModuleHandle(vcruntime140(d).dll) Disable GetModuleHandle(vcruntime140(d).dll) at sfx start 13 | win32 | Windows | 必须 Nessesary | 修改构建系统以静态构建 Modify build system for build sfx file 14 | zend_stream | Windows | 必须 Nessesary | 修改构建系统以静态构建 Modify build system for build sfx file 15 | comctl32 | Windows | 可选 Optional | 添加comctl32.dll manifest以启用[visual style](https://learn.microsoft.com/en-us/windows/win32/controls/visual-styles-overview) (会让窗口控件好看一些) Add manifest dependency for comctl32 to enable [visual style](https://learn.microsoft.com/en-us/windows/win32/controls/visual-styles-overview) (makes window control looks modern) 16 | 17 | ## Usage 18 | 19 | 目前补丁不需要特定顺序,使用 20 | 21 | ```bash 22 | # 在PHP源码目录 23 | patch -p1 < sapi/micro/patches/some_patch.patch 24 | ``` 25 | 26 | 来打patch 27 | 28 | Currently, patches do not require a specific order. Use 29 | 30 | ```bash 31 | # at PHP source root 32 | patch -p1 < sapi/micro/patches/some_patch.patch 33 | ``` 34 | 35 | to apply the patch. 36 | 37 | ### version choose 38 | 39 | patch文件名为\<名称\>.patch或者\<名称\>_\<版本\>.patch,如果没有版本号,说明这个补丁支持所有目前micro支持的PHP版本 40 | 41 | Patch file name is \.patch or \_\.patch. If there is no version number, it means that the patch supports all PHP versions that micro supports. 42 | 43 | 选择等于或者低于要打补丁的PHP版本的最新版本的patch,例如要给php 8.2打patch,有 80 81 84 三个patch, 则选择81 44 | 45 | Choose the latest patch that is equal to or lower than the PHP version you want to patch. For example, if you want to patch PHP 8.2, and there are patches 80 81 84, choose 81. 46 | 47 | 所有的补丁都是给最新的修正版本使用的 48 | 49 | All patches are applied to the latest patch version of its minor version. 50 | 51 | ## Something special 52 | 53 | ### phar.patch 54 | 55 | 这个patch绕过PHAR对micro的文件名中包含".phar"的限制(并不会允许micro本身以外的其他文件),这使得micro文件名中不含".phar"时依然可以使用压缩过的phar 56 | 57 | This patch bypasses the restriction that a PHAR file must contain '.phar' in its filename when invoked with micro (it will not allow files other than the sfx to be regarded as phar). This allows micro to handle compressed phar files without a custom stub. 58 | 59 | 有特别的stub的PHAR不需要这个补丁也可以使用 60 | 61 | phar with a stub (may be a special one) do not need this patch. 62 | 63 | 这个补丁只能在micro中使用,会导致其他SAPI编译不过 64 | 65 | This patch can only be used with micro, as it causes other SAPIs to fail to build. 66 | 67 | ### static_opcache 68 | 69 | 静态链接opcache到PHP里,可以在其他的SAPI上用 70 | 71 | This makes opcache statically linked into PHP, and it can be used for other SAPIs. 72 | 73 | PHP 8.3.11, 8.2.23中,opcache的config.m4发生了[变动](https://github.com/php/php-src/commit/d20d11375fa602236e1fb828f6a2236b19b43cdc),这个patch对应变动后的版本 74 | 75 | The opcache's config.m4 has [changed](https://github.com/php/php-src/commit/d20d11375fa602236e1fb828f6a2236b19b43cdc) in PHP 8.3.11 and 8.2.23, and this patch corresponds to the updated version. 76 | 77 | ### cli_checks 78 | 79 | 绕过许多硬编码的“是不是cli”的检查 80 | 81 | This bypasses many hard-coded cli SAPI name checks. 82 | 83 | ### cli_static 84 | 85 | 允许Windows的cli静态构建,不是给micro用的 86 | 87 | This allows the Windows cli SAPI to be built fully statically. It is not a patch for micro. 88 | -------------------------------------------------------------------------------- /patches/cli_checks_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c 2 | index bc5a6b2e23..710515b6c1 100644 3 | --- a/TSRM/tsrm_win32.c 4 | +++ b/TSRM/tsrm_win32.c 5 | @@ -531,7 +531,7 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, 6 | } 7 | 8 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 9 | - if (strcmp(sapi_module.name, "cli") != 0) { 10 | + if (strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 11 | dwCreateFlags |= CREATE_NO_WINDOW; 12 | } 13 | 14 | diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c 15 | index fc8bb9a1b0..2fd083d912 100644 16 | --- a/ext/ffi/ffi.c 17 | +++ b/ext/ffi/ffi.c 18 | @@ -4935,7 +4935,7 @@ ZEND_MINIT_FUNCTION(ffi) 19 | 20 | REGISTER_INI_ENTRIES(); 21 | 22 | - FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0; 23 | + FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0; 24 | 25 | INIT_NS_CLASS_ENTRY(ce, "FFI", "Exception", NULL); 26 | zend_ffi_exception_ce = zend_register_internal_class_ex(&ce, zend_ce_error); 27 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 28 | index c195ad7d2c..eef18fd10a 100644 29 | --- a/ext/opcache/ZendAccelerator.c 30 | +++ b/ext/opcache/ZendAccelerator.c 31 | @@ -2622,7 +2622,7 @@ static inline int accel_find_sapi(void) 32 | } 33 | } 34 | if (ZCG(accel_directives).enable_cli && ( 35 | - strcmp(sapi_module.name, "cli") == 0 36 | + strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 37 | || strcmp(sapi_module.name, "phpdbg") == 0)) { 38 | return SUCCESS; 39 | } 40 | @@ -2916,7 +2916,7 @@ static int accel_startup(zend_extension *extension) 41 | 42 | #ifdef HAVE_HUGE_CODE_PAGES 43 | if (ZCG(accel_directives).huge_code_pages && 44 | - (strcmp(sapi_module.name, "cli") == 0 || 45 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 || 46 | strcmp(sapi_module.name, "cli-server") == 0 || 47 | strcmp(sapi_module.name, "cgi-fcgi") == 0 || 48 | strcmp(sapi_module.name, "fpm-fcgi") == 0)) { 49 | @@ -2928,7 +2928,7 @@ static int accel_startup(zend_extension *extension) 50 | if (accel_find_sapi() == FAILURE) { 51 | accel_startup_ok = 0; 52 | if (!ZCG(accel_directives).enable_cli && 53 | - strcmp(sapi_module.name, "cli") == 0) { 54 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 55 | zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); 56 | } else { 57 | zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb); 58 | diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c 59 | index d9b9d94c6f..744c715b38 100644 60 | --- a/ext/pcre/php_pcre.c 61 | +++ b/ext/pcre/php_pcre.c 62 | @@ -291,7 +291,7 @@ static PHP_GINIT_FUNCTION(pcre) /* {{{ */ 63 | 64 | /* If we're on the CLI SAPI, there will only be one request, so we don't need the 65 | * cache to survive after RSHUTDOWN. */ 66 | - pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0; 67 | + pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0; 68 | if (!pcre_globals->per_request_cache) { 69 | zend_hash_init(&pcre_globals->pcre_cache, 0, NULL, php_free_pcre_cache, 1); 70 | } 71 | diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c 72 | index 2930796ae7..20ad2706c7 100644 73 | --- a/ext/readline/readline_cli.c 74 | +++ b/ext/readline/readline_cli.c 75 | @@ -721,7 +721,7 @@ typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void); 76 | get_cli_shell_callbacks get_callbacks; \ 77 | HMODULE hMod = GetModuleHandle("php.exe"); \ 78 | (cb) = NULL; \ 79 | - if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \ 80 | + if (0 == strncmp("cli", sapi_module.name, 3) || 0 == strncmp("micro", sapi_module.name, 5)) { \ 81 | get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \ 82 | if (get_callbacks) { \ 83 | (cb) = get_callbacks(); \ 84 | diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c 85 | index cd91e68fd3..f270eb5a15 100644 86 | --- a/ext/sqlite3/sqlite3.c 87 | +++ b/ext/sqlite3/sqlite3.c 88 | @@ -400,7 +400,7 @@ PHP_METHOD(SQLite3, loadExtension) 89 | 90 | #ifdef ZTS 91 | if ((strncmp(sapi_module.name, "cgi", 3) != 0) && 92 | - (strcmp(sapi_module.name, "cli") != 0) && 93 | + (strcmp(sapi_module.name, "cli") != 0) && (strcmp(sapi_module.name, "micro") != 0) && 94 | (strncmp(sapi_module.name, "embed", 5) != 0) 95 | ) { php_sqlite3_error(db_obj, "Not supported in multithreaded Web servers"); 96 | RETURN_FALSE; 97 | diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c 98 | index c5743c3361..b2dd79f5c4 100644 99 | --- a/ext/standard/php_fopen_wrapper.c 100 | +++ b/ext/standard/php_fopen_wrapper.c 101 | @@ -242,7 +242,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 102 | } 103 | return NULL; 104 | } 105 | - if (!strcmp(sapi_module.name, "cli")) { 106 | + if (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "micro")) { 107 | static int cli_in = 0; 108 | fd = STDIN_FILENO; 109 | if (cli_in) { 110 | @@ -258,7 +258,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 111 | pipe_requested = 1; 112 | #endif 113 | } else if (!strcasecmp(path, "stdout")) { 114 | - if (!strcmp(sapi_module.name, "cli")) { 115 | + if (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "micro")) { 116 | static int cli_out = 0; 117 | fd = STDOUT_FILENO; 118 | if (cli_out++) { 119 | @@ -274,7 +274,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 120 | pipe_requested = 1; 121 | #endif 122 | } else if (!strcasecmp(path, "stderr")) { 123 | - if (!strcmp(sapi_module.name, "cli")) { 124 | + if (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "micro")) { 125 | static int cli_err = 0; 126 | fd = STDERR_FILENO; 127 | if (cli_err++) { 128 | @@ -295,7 +295,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 129 | zend_long fildes_ori; 130 | int dtablesize; 131 | 132 | - if (strcmp(sapi_module.name, "cli")) { 133 | + if (strcmp(sapi_module.name, "cli") && strcmp(sapi_module.name, "micro")) { 134 | if (options & REPORT_ERRORS) { 135 | php_error_docref(NULL, E_WARNING, "Direct access to file descriptors is only available from command-line PHP"); 136 | } 137 | diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c 138 | index 03b55c3eac..5bb0472f76 100644 139 | --- a/ext/standard/proc_open.c 140 | +++ b/ext/standard/proc_open.c 141 | @@ -1136,7 +1136,7 @@ PHP_FUNCTION(proc_open) 142 | } 143 | 144 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 145 | - if(strcmp(sapi_module.name, "cli") != 0) { 146 | + if(strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 147 | dwCreateFlags |= CREATE_NO_WINDOW; 148 | } 149 | if (create_process_group) { 150 | diff --git a/main/main.c b/main/main.c 151 | index 7bd5400760..f0a71d7915 100644 152 | --- a/main/main.c 153 | +++ b/main/main.c 154 | @@ -480,7 +480,7 @@ static PHP_INI_DISP(display_errors_mode) 155 | mode = php_get_display_errors_mode(tmp_value, tmp_value_length); 156 | 157 | /* Display 'On' for other SAPIs instead of STDOUT or STDERR */ 158 | - cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")); 159 | + cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")); 160 | 161 | switch (mode) { 162 | case PHP_DISPLAY_ERRORS_STDERR: 163 | diff --git a/win32/console.c b/win32/console.c 164 | index 7833dd97d3..1fa8e4cea9 100644 165 | --- a/win32/console.c 166 | +++ b/win32/console.c 167 | @@ -111,6 +111,6 @@ PHP_WINUTIL_API BOOL php_win32_console_is_own(void) 168 | 169 | PHP_WINUTIL_API BOOL php_win32_console_is_cli_sapi(void) 170 | {/*{{{*/ 171 | - return strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1); 172 | + return !strncmp(sapi_module.name, "cli", sizeof("cli") - 1) || !strncmp(sapi_module.name, "micro", sizeof("micro") - 1); 173 | }/*}}}*/ 174 | 175 | -------------------------------------------------------------------------------- /patches/cli_checks_81.patch: -------------------------------------------------------------------------------- 1 | diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c 2 | index cfe344e377..7e1a5ca54f 100644 3 | --- a/TSRM/tsrm_win32.c 4 | +++ b/TSRM/tsrm_win32.c 5 | @@ -531,7 +531,7 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, 6 | } 7 | 8 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 9 | - if (strcmp(sapi_module.name, "cli") != 0) { 10 | + if (strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 11 | dwCreateFlags |= CREATE_NO_WINDOW; 12 | } 13 | 14 | diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c 15 | index 8f05686367..c155028233 100644 16 | --- a/ext/ffi/ffi.c 17 | +++ b/ext/ffi/ffi.c 18 | @@ -5247,7 +5247,7 @@ ZEND_MINIT_FUNCTION(ffi) 19 | { 20 | REGISTER_INI_ENTRIES(); 21 | 22 | - FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0; 23 | + FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 1; 24 | 25 | zend_ffi_exception_ce = register_class_FFI_Exception(zend_ce_error); 26 | 27 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 28 | index 5f6b854d47..2b8362c412 100644 29 | --- a/ext/opcache/ZendAccelerator.c 30 | +++ b/ext/opcache/ZendAccelerator.c 31 | @@ -2830,7 +2830,7 @@ static inline int accel_find_sapi(void) 32 | } 33 | if (ZCG(accel_directives).enable_cli && ( 34 | strcmp(sapi_module.name, "cli") == 0 35 | - || strcmp(sapi_module.name, "phpdbg") == 0)) { 36 | + || strcmp(sapi_module.name, "phpdbg") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 37 | return SUCCESS; 38 | } 39 | } 40 | @@ -3128,7 +3128,7 @@ static int accel_startup(zend_extension *extension) 41 | 42 | #ifdef HAVE_HUGE_CODE_PAGES 43 | if (ZCG(accel_directives).huge_code_pages && 44 | - (strcmp(sapi_module.name, "cli") == 0 || 45 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 || 46 | strcmp(sapi_module.name, "cli-server") == 0 || 47 | strcmp(sapi_module.name, "cgi-fcgi") == 0 || 48 | strcmp(sapi_module.name, "fpm-fcgi") == 0)) { 49 | @@ -3140,7 +3140,7 @@ static int accel_startup(zend_extension *extension) 50 | if (accel_find_sapi() == FAILURE) { 51 | accel_startup_ok = 0; 52 | if (!ZCG(accel_directives).enable_cli && 53 | - strcmp(sapi_module.name, "cli") == 0) { 54 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 55 | zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); 56 | } else { 57 | zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb); 58 | diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c 59 | index a8d3559ef5..1b40f94643 100644 60 | --- a/ext/pcre/php_pcre.c 61 | +++ b/ext/pcre/php_pcre.c 62 | @@ -291,7 +291,7 @@ static PHP_GINIT_FUNCTION(pcre) /* {{{ */ 63 | 64 | /* If we're on the CLI SAPI, there will only be one request, so we don't need the 65 | * cache to survive after RSHUTDOWN. */ 66 | - pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0; 67 | + pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0; 68 | if (!pcre_globals->per_request_cache) { 69 | zend_hash_init(&pcre_globals->pcre_cache, 0, NULL, php_free_pcre_cache, 1); 70 | } 71 | diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c 72 | index 8bf5d23df7..9af99ada0b 100644 73 | --- a/ext/readline/readline_cli.c 74 | +++ b/ext/readline/readline_cli.c 75 | @@ -735,7 +735,7 @@ typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void); 76 | get_cli_shell_callbacks get_callbacks; \ 77 | HMODULE hMod = GetModuleHandle("php.exe"); \ 78 | (cb) = NULL; \ 79 | - if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \ 80 | + if ((strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) || 0 == strcmp("micro", sapi_module.name)) { \ 81 | get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \ 82 | if (get_callbacks) { \ 83 | (cb) = get_callbacks(); \ 84 | diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c 85 | index 007eef7a74..86d75103c8 100644 86 | --- a/ext/sqlite3/sqlite3.c 87 | +++ b/ext/sqlite3/sqlite3.c 88 | @@ -399,7 +399,7 @@ PHP_METHOD(SQLite3, loadExtension) 89 | 90 | #ifdef ZTS 91 | if ((strncmp(sapi_module.name, "cgi", 3) != 0) && 92 | - (strcmp(sapi_module.name, "cli") != 0) && 93 | + (strcmp(sapi_module.name, "cli") != 0) && (strcmp(sapi_module.name, "micro") != 0) && 94 | (strncmp(sapi_module.name, "embed", 5) != 0) 95 | ) { php_sqlite3_error(db_obj, "Not supported in multithreaded Web servers"); 96 | RETURN_FALSE; 97 | diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c 98 | index 4287045511..eab0311d07 100644 99 | --- a/ext/standard/php_fopen_wrapper.c 100 | +++ b/ext/standard/php_fopen_wrapper.c 101 | @@ -242,7 +242,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 102 | } 103 | return NULL; 104 | } 105 | - if (!strcmp(sapi_module.name, "cli")) { 106 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 107 | static int cli_in = 0; 108 | fd = STDIN_FILENO; 109 | if (cli_in) { 110 | @@ -258,7 +258,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 111 | pipe_requested = 1; 112 | #endif 113 | } else if (!strcasecmp(path, "stdout")) { 114 | - if (!strcmp(sapi_module.name, "cli")) { 115 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 116 | static int cli_out = 0; 117 | fd = STDOUT_FILENO; 118 | if (cli_out++) { 119 | @@ -274,7 +274,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 120 | pipe_requested = 1; 121 | #endif 122 | } else if (!strcasecmp(path, "stderr")) { 123 | - if (!strcmp(sapi_module.name, "cli")) { 124 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 125 | static int cli_err = 0; 126 | fd = STDERR_FILENO; 127 | if (cli_err++) { 128 | @@ -295,7 +295,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 129 | zend_long fildes_ori; 130 | int dtablesize; 131 | 132 | - if (strcmp(sapi_module.name, "cli")) { 133 | + if (strcmp(sapi_module.name, "cli") || strcmp(sapi_module.name, "micro")) { 134 | if (options & REPORT_ERRORS) { 135 | php_error_docref(NULL, E_WARNING, "Direct access to file descriptors is only available from command-line PHP"); 136 | } 137 | diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c 138 | index a57e66bd97..e9044cd34e 100644 139 | --- a/ext/standard/proc_open.c 140 | +++ b/ext/standard/proc_open.c 141 | @@ -1135,7 +1135,7 @@ PHP_FUNCTION(proc_open) 142 | } 143 | 144 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 145 | - if(strcmp(sapi_module.name, "cli") != 0) { 146 | + if(strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 147 | dwCreateFlags |= CREATE_NO_WINDOW; 148 | } 149 | if (create_process_group) { 150 | diff --git a/main/main.c b/main/main.c 151 | index dc705fcdbd..a206aa11e4 100644 152 | --- a/main/main.c 153 | +++ b/main/main.c 154 | @@ -475,7 +475,7 @@ static PHP_INI_DISP(display_errors_mode) 155 | mode = php_get_display_errors_mode(temporary_value); 156 | 157 | /* Display 'On' for other SAPIs instead of STDOUT or STDERR */ 158 | - cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")); 159 | + cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")); 160 | 161 | switch (mode) { 162 | case PHP_DISPLAY_ERRORS_STDERR: 163 | @@ -1340,7 +1340,7 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c 164 | } 165 | } else { 166 | /* Write CLI/CGI errors to stderr if display_errors = "stderr" */ 167 | - if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) && 168 | + if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")) && 169 | PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR 170 | ) { 171 | fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno); 172 | diff --git a/win32/console.c b/win32/console.c 173 | index 9b48561088..a2b764cdb5 100644 174 | --- a/win32/console.c 175 | +++ b/win32/console.c 176 | @@ -111,6 +111,6 @@ PHP_WINUTIL_API BOOL php_win32_console_is_own(void) 177 | 178 | PHP_WINUTIL_API BOOL php_win32_console_is_cli_sapi(void) 179 | {/*{{{*/ 180 | - return strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1); 181 | + return (strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1)) || 0 == strcmp(sapi_module.name, "micro"); 182 | }/*}}}*/ 183 | 184 | -------------------------------------------------------------------------------- /patches/cli_checks_83.patch: -------------------------------------------------------------------------------- 1 | diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c 2 | index dc8f9fefa3..057d76229e 100644 3 | --- a/TSRM/tsrm_win32.c 4 | +++ b/TSRM/tsrm_win32.c 5 | @@ -530,7 +530,7 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, 6 | } 7 | 8 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 9 | - if (strcmp(sapi_module.name, "cli") != 0) { 10 | + if (strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 11 | dwCreateFlags |= CREATE_NO_WINDOW; 12 | } 13 | 14 | diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c 15 | index bbfe07576e..398373d577 100644 16 | --- a/ext/ffi/ffi.c 17 | +++ b/ext/ffi/ffi.c 18 | @@ -5402,7 +5402,7 @@ ZEND_MINIT_FUNCTION(ffi) 19 | { 20 | REGISTER_INI_ENTRIES(); 21 | 22 | - FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0; 23 | + FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 1; 24 | 25 | zend_ffi_exception_ce = register_class_FFI_Exception(zend_ce_error); 26 | 27 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 28 | index a21c640d91..3af0e89b21 100644 29 | --- a/ext/opcache/ZendAccelerator.c 30 | +++ b/ext/opcache/ZendAccelerator.c 31 | @@ -2822,7 +2822,7 @@ static inline zend_result accel_find_sapi(void) 32 | } 33 | if (ZCG(accel_directives).enable_cli && ( 34 | strcmp(sapi_module.name, "cli") == 0 35 | - || strcmp(sapi_module.name, "phpdbg") == 0)) { 36 | + || strcmp(sapi_module.name, "phpdbg") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 37 | return SUCCESS; 38 | } 39 | } 40 | @@ -3127,7 +3127,7 @@ static int accel_startup(zend_extension *extension) 41 | 42 | #ifdef HAVE_HUGE_CODE_PAGES 43 | if (ZCG(accel_directives).huge_code_pages && 44 | - (strcmp(sapi_module.name, "cli") == 0 || 45 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 || 46 | strcmp(sapi_module.name, "cli-server") == 0 || 47 | strcmp(sapi_module.name, "cgi-fcgi") == 0 || 48 | strcmp(sapi_module.name, "fpm-fcgi") == 0)) { 49 | @@ -3139,7 +3139,7 @@ static int accel_startup(zend_extension *extension) 50 | if (accel_find_sapi() == FAILURE) { 51 | accel_startup_ok = false; 52 | if (!ZCG(accel_directives).enable_cli && 53 | - strcmp(sapi_module.name, "cli") == 0) { 54 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 55 | zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); 56 | } else { 57 | zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI, FrankenPHP, LiteSpeed and uWSGI SAPIs", NULL, accelerator_remove_cb); 58 | @@ -4681,7 +4681,7 @@ static zend_result accel_finish_startup_preload_subprocess(pid_t *pid) 59 | if (!ZCG(accel_directives).preload_user 60 | || !*ZCG(accel_directives).preload_user) { 61 | 62 | - bool sapi_requires_preload_user = !(strcmp(sapi_module.name, "cli") == 0 63 | + bool sapi_requires_preload_user = !(strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 64 | || strcmp(sapi_module.name, "phpdbg") == 0); 65 | 66 | if (!sapi_requires_preload_user) { 67 | diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c 68 | index 6ad0b6eb76..7c9861678f 100644 69 | --- a/ext/pcre/php_pcre.c 70 | +++ b/ext/pcre/php_pcre.c 71 | @@ -300,7 +300,7 @@ static PHP_GINIT_FUNCTION(pcre) /* {{{ */ 72 | 73 | /* If we're on the CLI SAPI, there will only be one request, so we don't need the 74 | * cache to survive after RSHUTDOWN. */ 75 | - pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0; 76 | + pcre_globals->per_request_cache = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0; 77 | if (!pcre_globals->per_request_cache) { 78 | zend_hash_init(&pcre_globals->pcre_cache, 0, NULL, php_free_pcre_cache, 1); 79 | } 80 | diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c 81 | index 8fbe93d648..3c14946e58 100644 82 | --- a/ext/readline/readline_cli.c 83 | +++ b/ext/readline/readline_cli.c 84 | @@ -736,7 +736,7 @@ typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void); 85 | get_cli_shell_callbacks get_callbacks; \ 86 | HMODULE hMod = GetModuleHandle("php.exe"); \ 87 | (cb) = NULL; \ 88 | - if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \ 89 | + if ((strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) || 0 == strcmp("micro", sapi_module.name)) { \ 90 | get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \ 91 | if (get_callbacks) { \ 92 | (cb) = get_callbacks(); \ 93 | diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c 94 | index badcfcc29b..70d4d5423e 100644 95 | --- a/ext/sqlite3/sqlite3.c 96 | +++ b/ext/sqlite3/sqlite3.c 97 | @@ -402,7 +402,7 @@ PHP_METHOD(SQLite3, loadExtension) 98 | 99 | #ifdef ZTS 100 | if ((strncmp(sapi_module.name, "cgi", 3) != 0) && 101 | - (strcmp(sapi_module.name, "cli") != 0) && 102 | + (strcmp(sapi_module.name, "cli") != 0) && (strcmp(sapi_module.name, "micro") != 0) && 103 | (strncmp(sapi_module.name, "embed", 5) != 0) 104 | ) { php_sqlite3_error(db_obj, 0, "Not supported in multithreaded Web servers"); 105 | RETURN_FALSE; 106 | diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c 107 | index 8926485025..6740163bc5 100644 108 | --- a/ext/standard/php_fopen_wrapper.c 109 | +++ b/ext/standard/php_fopen_wrapper.c 110 | @@ -242,7 +242,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 111 | } 112 | return NULL; 113 | } 114 | - if (!strcmp(sapi_module.name, "cli")) { 115 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 116 | static int cli_in = 0; 117 | fd = STDIN_FILENO; 118 | if (cli_in) { 119 | @@ -258,7 +258,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 120 | pipe_requested = 1; 121 | #endif 122 | } else if (!strcasecmp(path, "stdout")) { 123 | - if (!strcmp(sapi_module.name, "cli")) { 124 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 125 | static int cli_out = 0; 126 | fd = STDOUT_FILENO; 127 | if (cli_out++) { 128 | @@ -274,7 +274,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 129 | pipe_requested = 1; 130 | #endif 131 | } else if (!strcasecmp(path, "stderr")) { 132 | - if (!strcmp(sapi_module.name, "cli")) { 133 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 134 | static int cli_err = 0; 135 | fd = STDERR_FILENO; 136 | if (cli_err++) { 137 | @@ -295,7 +295,7 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa 138 | zend_long fildes_ori; 139 | int dtablesize; 140 | 141 | - if (strcmp(sapi_module.name, "cli")) { 142 | + if (strcmp(sapi_module.name, "cli") || strcmp(sapi_module.name, "micro")) { 143 | if (options & REPORT_ERRORS) { 144 | php_error_docref(NULL, E_WARNING, "Direct access to file descriptors is only available from command-line PHP"); 145 | } 146 | diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c 147 | index 2d4cb42b7a..726d995dc0 100644 148 | --- a/ext/standard/proc_open.c 149 | +++ b/ext/standard/proc_open.c 150 | @@ -1280,7 +1280,7 @@ PHP_FUNCTION(proc_open) 151 | } 152 | 153 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 154 | - if(strcmp(sapi_module.name, "cli") != 0) { 155 | + if(strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 156 | dwCreateFlags |= CREATE_NO_WINDOW; 157 | } 158 | if (create_process_group) { 159 | diff --git a/main/main.c b/main/main.c 160 | index 3c9c55129e..cb8fb42eea 100644 161 | --- a/main/main.c 162 | +++ b/main/main.c 163 | @@ -486,7 +486,7 @@ static PHP_INI_DISP(display_errors_mode) 164 | mode = php_get_display_errors_mode(temporary_value); 165 | 166 | /* Display 'On' for other SAPIs instead of STDOUT or STDERR */ 167 | - cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")); 168 | + cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")); 169 | 170 | switch (mode) { 171 | case PHP_DISPLAY_ERRORS_STDERR: 172 | @@ -1367,7 +1367,7 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c 173 | } 174 | } else { 175 | /* Write CLI/CGI errors to stderr if display_errors = "stderr" */ 176 | - if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) && 177 | + if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")) && 178 | PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR 179 | ) { 180 | fprintf(stderr, "%s: ", error_type_str); 181 | diff --git a/win32/console.c b/win32/console.c 182 | index 9b48561088..a2b764cdb5 100644 183 | --- a/win32/console.c 184 | +++ b/win32/console.c 185 | @@ -111,6 +111,6 @@ PHP_WINUTIL_API BOOL php_win32_console_is_own(void) 186 | 187 | PHP_WINUTIL_API BOOL php_win32_console_is_cli_sapi(void) 188 | {/*{{{*/ 189 | - return strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1); 190 | + return (strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1)) || 0 == strcmp(sapi_module.name, "micro"); 191 | }/*}}}*/ 192 | 193 | -------------------------------------------------------------------------------- /patches/cli_checks_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c 2 | index dc8f9fefa3..057d76229e 100644 3 | --- a/TSRM/tsrm_win32.c 4 | +++ b/TSRM/tsrm_win32.c 5 | @@ -530,7 +530,7 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, 6 | } 7 | 8 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 9 | - if (strcmp(sapi_module.name, "cli") != 0) { 10 | + if (strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 11 | dwCreateFlags |= CREATE_NO_WINDOW; 12 | } 13 | 14 | diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c 15 | index d797f5f93f..27cb05e3e4 100644 16 | --- a/ext/ffi/ffi.c 17 | +++ b/ext/ffi/ffi.c 18 | @@ -5403,7 +5403,7 @@ ZEND_MINIT_FUNCTION(ffi) 19 | { 20 | REGISTER_INI_ENTRIES(); 21 | 22 | - FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0; 23 | + FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 1; 24 | 25 | zend_ffi_exception_ce = register_class_FFI_Exception(zend_ce_error); 26 | 27 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 28 | index 8d45b2ae41..35e9403a31 100644 29 | --- a/ext/opcache/ZendAccelerator.c 30 | +++ b/ext/opcache/ZendAccelerator.c 31 | @@ -2822,7 +2822,7 @@ static inline zend_result accel_find_sapi(void) 32 | } 33 | if (ZCG(accel_directives).enable_cli && ( 34 | strcmp(sapi_module.name, "cli") == 0 35 | - || strcmp(sapi_module.name, "phpdbg") == 0)) { 36 | + || strcmp(sapi_module.name, "phpdbg") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 37 | return SUCCESS; 38 | } 39 | } 40 | @@ -3134,7 +3134,7 @@ static int accel_startup(zend_extension *extension) 41 | 42 | #ifdef HAVE_HUGE_CODE_PAGES 43 | if (ZCG(accel_directives).huge_code_pages && 44 | - (strcmp(sapi_module.name, "cli") == 0 || 45 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 || 46 | strcmp(sapi_module.name, "cli-server") == 0 || 47 | strcmp(sapi_module.name, "cgi-fcgi") == 0 || 48 | strcmp(sapi_module.name, "fpm-fcgi") == 0)) { 49 | @@ -3146,7 +3146,7 @@ static int accel_startup(zend_extension *extension) 50 | if (accel_find_sapi() == FAILURE) { 51 | accel_startup_ok = false; 52 | if (!ZCG(accel_directives).enable_cli && 53 | - strcmp(sapi_module.name, "cli") == 0) { 54 | + (strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0)) { 55 | zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); 56 | } else { 57 | zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI, FrankenPHP, LiteSpeed and uWSGI SAPIs", NULL, accelerator_remove_cb); 58 | @@ -4685,7 +4685,7 @@ static zend_result accel_finish_startup_preload_subprocess(pid_t *pid) 59 | if (!ZCG(accel_directives).preload_user 60 | || !*ZCG(accel_directives).preload_user) { 61 | 62 | - bool sapi_requires_preload_user = !(strcmp(sapi_module.name, "cli") == 0 63 | + bool sapi_requires_preload_user = !(strcmp(sapi_module.name, "cli") == 0 || strcmp(sapi_module.name, "micro") == 0 64 | || strcmp(sapi_module.name, "phpdbg") == 0); 65 | 66 | if (!sapi_requires_preload_user) { 67 | diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c 68 | index 49a477998b..18fe71cce4 100644 69 | --- a/ext/pdo_sqlite/pdo_sqlite.c 70 | +++ b/ext/pdo_sqlite/pdo_sqlite.c 71 | @@ -94,6 +94,7 @@ PHP_METHOD(Pdo_Sqlite, loadExtension) 72 | #ifdef ZTS 73 | if ((strncmp(sapi_module.name, "cgi", 3) != 0) && 74 | (strcmp(sapi_module.name, "cli") != 0) && 75 | + (strcmp(sapi_module.name, "micro") != 0) && 76 | (strncmp(sapi_module.name, "embed", 5) != 0) 77 | ) { 78 | zend_throw_exception_ex(php_pdo_get_exception(), 0, "Not supported in multithreaded Web servers"); 79 | diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c 80 | index 80ddd88f7d..7b37aaff0b 100644 81 | --- a/ext/readline/readline_cli.c 82 | +++ b/ext/readline/readline_cli.c 83 | @@ -730,7 +730,7 @@ typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void); 84 | get_cli_shell_callbacks get_callbacks; \ 85 | HMODULE hMod = GetModuleHandle("php.exe"); \ 86 | (cb) = NULL; \ 87 | - if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \ 88 | + if ((strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) || 0 == strcmp("micro", sapi_module.name)) { \ 89 | get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \ 90 | if (get_callbacks) { \ 91 | (cb) = get_callbacks(); \ 92 | diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c 93 | index 0f26593b85..5f253f0061 100644 94 | --- a/ext/sqlite3/sqlite3.c 95 | +++ b/ext/sqlite3/sqlite3.c 96 | @@ -408,7 +408,7 @@ PHP_METHOD(SQLite3, loadExtension) 97 | 98 | #ifdef ZTS 99 | if ((strncmp(sapi_module.name, "cgi", 3) != 0) && 100 | - (strcmp(sapi_module.name, "cli") != 0) && 101 | + (strcmp(sapi_module.name, "cli") != 0) && (strcmp(sapi_module.name, "micro") != 0) && 102 | (strncmp(sapi_module.name, "embed", 5) != 0) 103 | ) { php_sqlite3_error(db_obj, 0, "Not supported in multithreaded Web servers"); 104 | RETURN_FALSE; 105 | diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c 106 | index a5581d9ccc..98455f7b52 100644 107 | --- a/ext/standard/php_fopen_wrapper.c 108 | +++ b/ext/standard/php_fopen_wrapper.c 109 | @@ -242,7 +242,7 @@ static php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const c 110 | } 111 | return NULL; 112 | } 113 | - if (!strcmp(sapi_module.name, "cli")) { 114 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 115 | static int cli_in = 0; 116 | fd = STDIN_FILENO; 117 | if (cli_in) { 118 | @@ -258,7 +258,7 @@ static php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const c 119 | pipe_requested = 1; 120 | #endif 121 | } else if (!strcasecmp(path, "stdout")) { 122 | - if (!strcmp(sapi_module.name, "cli")) { 123 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 124 | static int cli_out = 0; 125 | fd = STDOUT_FILENO; 126 | if (cli_out++) { 127 | @@ -274,7 +274,7 @@ static php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const c 128 | pipe_requested = 1; 129 | #endif 130 | } else if (!strcasecmp(path, "stderr")) { 131 | - if (!strcmp(sapi_module.name, "cli")) { 132 | + if (!strcmp(sapi_module.name, "cli") && !strcmp(sapi_module.name, "micro")) { 133 | static int cli_err = 0; 134 | fd = STDERR_FILENO; 135 | if (cli_err++) { 136 | @@ -295,7 +295,7 @@ static php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const c 137 | zend_long fildes_ori; 138 | int dtablesize; 139 | 140 | - if (strcmp(sapi_module.name, "cli")) { 141 | + if (strcmp(sapi_module.name, "cli") || strcmp(sapi_module.name, "micro")) { 142 | if (options & REPORT_ERRORS) { 143 | php_error_docref(NULL, E_WARNING, "Direct access to file descriptors is only available from command-line PHP"); 144 | } 145 | diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c 146 | index d935f9d216..bac478144d 100644 147 | --- a/ext/standard/proc_open.c 148 | +++ b/ext/standard/proc_open.c 149 | @@ -1274,7 +1274,7 @@ PHP_FUNCTION(proc_open) 150 | } 151 | 152 | dwCreateFlags = NORMAL_PRIORITY_CLASS; 153 | - if(strcmp(sapi_module.name, "cli") != 0) { 154 | + if(strcmp(sapi_module.name, "cli") != 0 && strcmp(sapi_module.name, "micro") != 0) { 155 | dwCreateFlags |= CREATE_NO_WINDOW; 156 | } 157 | if (create_process_group) { 158 | diff --git a/main/main.c b/main/main.c 159 | index a3acaf94b7..7ac56f9919 100644 160 | --- a/main/main.c 161 | +++ b/main/main.c 162 | @@ -486,7 +486,7 @@ static PHP_INI_DISP(display_errors_mode) 163 | mode = php_get_display_errors_mode(temporary_value); 164 | 165 | /* Display 'On' for other SAPIs instead of STDOUT or STDERR */ 166 | - cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")); 167 | + cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")); 168 | 169 | switch (mode) { 170 | case PHP_DISPLAY_ERRORS_STDERR: 171 | @@ -1371,7 +1371,7 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c 172 | } 173 | } else { 174 | /* Write CLI/CGI errors to stderr if display_errors = "stderr" */ 175 | - if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) && 176 | + if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg") || !strcmp(sapi_module.name, "micro")) && 177 | PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR 178 | ) { 179 | fprintf(stderr, "%s: ", error_type_str); 180 | diff --git a/win32/console.c b/win32/console.c 181 | index 9b48561088..a2b764cdb5 100644 182 | --- a/win32/console.c 183 | +++ b/win32/console.c 184 | @@ -111,6 +111,6 @@ PHP_WINUTIL_API BOOL php_win32_console_is_own(void) 185 | 186 | PHP_WINUTIL_API BOOL php_win32_console_is_cli_sapi(void) 187 | {/*{{{*/ 188 | - return strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1); 189 | + return (strlen(sapi_module.name) >= sizeof("cli") - 1 && !strncmp(sapi_module.name, "cli", sizeof("cli") - 1)) || 0 == strcmp(sapi_module.name, "micro"); 190 | }/*}}}*/ 191 | 192 | -------------------------------------------------------------------------------- /patches/cli_static_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c 2 | index 0ad53e813c..a8cc1bee29 100644 3 | --- a/sapi/cli/php_cli.c 4 | +++ b/sapi/cli/php_cli.c 5 | @@ -97,7 +97,7 @@ PHPAPI extern char *php_ini_scanned_files; 6 | 7 | #if defined(PHP_WIN32) 8 | #if defined(ZTS) 9 | -ZEND_TSRMLS_CACHE_DEFINE() 10 | +//ZEND_TSRMLS_CACHE_DEFINE() 11 | #endif 12 | static DWORD orig_cp = 0; 13 | #endif 14 | @@ -1160,6 +1160,11 @@ int main(int argc, char *argv[]) 15 | #endif 16 | { 17 | #if defined(PHP_WIN32) 18 | + php_win32_init_gettimeofday(); 19 | + if (!php_win32_ioutil_init()) { 20 | + fprintf(stderr, "ioutil initialization failed"); 21 | + return 1; 22 | + } 23 | # ifdef PHP_CLI_WIN32_NO_CONSOLE 24 | int argc = __argc; 25 | char **argv = __argv; 26 | -------------------------------------------------------------------------------- /patches/cli_static_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c 2 | --- a/sapi/cli/php_cli.c (revision d3bf67d44102869f340a7be0e12f4f09de0edbcf) 3 | +++ b/sapi/cli/php_cli.c (date 1735128770216) 4 | @@ -98,7 +98,7 @@ 5 | 6 | #if defined(PHP_WIN32) 7 | #if defined(ZTS) 8 | -ZEND_TSRMLS_CACHE_DEFINE() 9 | +//ZEND_TSRMLS_CACHE_DEFINE() 10 | #endif 11 | static DWORD orig_cp = 0; 12 | #endif 13 | @@ -1137,6 +1137,10 @@ 14 | #endif 15 | { 16 | #if defined(PHP_WIN32) 17 | + if (!php_win32_ioutil_init()) { 18 | + fprintf(stderr, "ioutil initialization failed"); 19 | + return 1; 20 | + } 21 | # ifdef PHP_CLI_WIN32_NO_CONSOLE 22 | int argc = __argc; 23 | char **argv = __argv; 24 | -------------------------------------------------------------------------------- /patches/comctl32.patch: -------------------------------------------------------------------------------- 1 | diff --git a/win32/build/default.manifest b/win32/build/default.manifest 2 | index a73c2fb53d..52351251e1 100644 3 | --- a/win32/build/default.manifest 4 | +++ b/win32/build/default.manifest 5 | @@ -24,4 +24,16 @@ 6 | true 7 | 8 | 9 | + 10 | + 11 | + 19 | + 20 | + 21 | 22 | -------------------------------------------------------------------------------- /patches/disable_huge_page_80.patch: -------------------------------------------------------------------------------- 1 | --- php-8.0.0/configure.ac 2020-11-25 01:04:03.000000000 +0800 2 | +++ php-8.0.0-micro/configure.ac 2020-11-29 20:00:13.256181206 +0800 3 | @@ -1005,7 +1005,7 @@ dnl Extensions post-config. 4 | dnl ---------------------------------------------------------------------------- 5 | 6 | dnl Align segments on huge page boundary 7 | -case $host_alias in 8 | +case nope in 9 | i[[3456]]86-*-linux-* | x86_64-*-linux-*) 10 | AC_MSG_CHECKING(linker support for -zcommon-page-size=2097152) 11 | save_LDFLAGS=$LDFLAGS 12 | -------------------------------------------------------------------------------- /patches/disable_huge_page_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/configure.ac b/configure.ac 2 | index 48778c7bd2..760c4f2670 100644 3 | --- a/configure.ac 4 | +++ b/configure.ac 5 | @@ -1127,7 +1127,7 @@ dnl Extensions post-config. 6 | dnl ---------------------------------------------------------------------------- 7 | 8 | dnl Align segments on huge page boundary 9 | -AS_CASE([$host_alias], [[i[3456]86-*-linux-* | x86_64-*-linux-*]], 10 | +AS_CASE([nope], [[i[3456]86-*-linux-* | x86_64-*-linux-*]], 11 | [AC_CACHE_CHECK([linker support for -zcommon-page-size=2097152], 12 | [php_cv_have_common_page_size], [ 13 | save_LDFLAGS=$LDFLAGS 14 | -------------------------------------------------------------------------------- /patches/macos_iconv_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/php.m4 b/build/php.m4 2 | index 01b8250598..0a8c5fba53 100644 3 | --- a/build/php.m4 4 | +++ b/build/php.m4 5 | @@ -1963,9 +1963,7 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 6 | 7 | dnl Check libc first if no path is provided in --with-iconv. 8 | if test "$PHP_ICONV" = "yes"; then 9 | - dnl Reset LIBS temporarily as it may have already been included -liconv in. 10 | - LIBS_save="$LIBS" 11 | - LIBS= 12 | + LIBS="$LIBS -liconv" 13 | AC_CHECK_FUNC(iconv, [ 14 | found_iconv=yes 15 | ],[ 16 | @@ -1974,7 +1972,6 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 17 | found_iconv=yes 18 | ]) 19 | ]) 20 | - LIBS="$LIBS_save" 21 | fi 22 | 23 | dnl Check external libs for iconv funcs. 24 | -------------------------------------------------------------------------------- /patches/macos_iconv_81.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/php.m4 b/build/php.m4 2 | index 01b8250598..0a8c5fba53 100644 3 | --- a/build/php.m4 4 | +++ b/build/php.m4 5 | @@ -1963,9 +1963,7 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 6 | 7 | dnl Check libc first if no path is provided in --with-iconv. 8 | if test "$PHP_ICONV" = "yes"; then 9 | - dnl Reset LIBS temporarily as it may have already been included -liconv in. 10 | - LIBS_save="$LIBS" 11 | - LIBS= 12 | + LIBS="$LIBS -liconv" 13 | AC_CHECK_FUNC(iconv, [ 14 | found_iconv=yes 15 | ],[ 16 | @@ -1974,7 +1972,6 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 17 | found_iconv=yes 18 | ]) 19 | ]) 20 | - LIBS="$LIBS_save" 21 | fi 22 | 23 | dnl Check external libs for iconv funcs. 24 | -------------------------------------------------------------------------------- /patches/macos_iconv_82.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/php.m4 b/build/php.m4 2 | index 01b8250598..0a8c5fba53 100644 3 | --- a/build/php.m4 4 | +++ b/build/php.m4 5 | @@ -1963,9 +1963,7 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 6 | 7 | dnl Check libc first if no path is provided in --with-iconv. 8 | if test "$PHP_ICONV" = "yes"; then 9 | - dnl Reset LIBS temporarily as it may have already been included -liconv in. 10 | - LIBS_save="$LIBS" 11 | - LIBS= 12 | + LIBS="$LIBS -liconv" 13 | AC_CHECK_FUNC(iconv, [ 14 | found_iconv=yes 15 | ],[ 16 | @@ -1974,7 +1972,6 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 17 | found_iconv=yes 18 | ]) 19 | ]) 20 | - LIBS="$LIBS_save" 21 | fi 22 | 23 | dnl Check external libs for iconv funcs. 24 | -------------------------------------------------------------------------------- /patches/macos_iconv_83.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/php.m4 b/build/php.m4 2 | index 01b8250598..0a8c5fba53 100644 3 | --- a/build/php.m4 4 | +++ b/build/php.m4 5 | @@ -1963,9 +1963,7 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 6 | 7 | dnl Check libc first if no path is provided in --with-iconv. 8 | if test "$PHP_ICONV" = "yes"; then 9 | - dnl Reset LIBS temporarily as it may have already been included -liconv in. 10 | - LIBS_save="$LIBS" 11 | - LIBS= 12 | + LIBS="$LIBS -liconv" 13 | AC_CHECK_FUNC(iconv, [ 14 | found_iconv=yes 15 | ],[ 16 | @@ -1974,7 +1972,6 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 17 | found_iconv=yes 18 | ]) 19 | ]) 20 | - LIBS="$LIBS_save" 21 | fi 22 | 23 | dnl Check external libs for iconv funcs. 24 | -------------------------------------------------------------------------------- /patches/macos_iconv_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/php.m4 b/build/php.m4 2 | index e45b22b766..506be904f1 100644 3 | --- a/build/php.m4 4 | +++ b/build/php.m4 5 | @@ -1821,15 +1821,12 @@ AC_DEFUN([PHP_SETUP_ICONV], [ 6 | 7 | dnl Check libc first if no path is provided in --with-iconv. 8 | AS_VAR_IF([PHP_ICONV], [yes], [ 9 | - dnl Reset LIBS temporarily as it may have already been included -liconv in. 10 | - LIBS_save=$LIBS 11 | - LIBS= 12 | + LIBS="$LIBS -liconv" 13 | AC_CHECK_FUNC([iconv], [found_iconv=yes], 14 | [AC_CHECK_FUNC([libiconv], [ 15 | AC_DEFINE([HAVE_LIBICONV], [1]) 16 | found_iconv=yes 17 | ])]) 18 | - LIBS=$LIBS_save 19 | ]) 20 | 21 | dnl Check external libs for iconv funcs. 22 | -------------------------------------------------------------------------------- /patches/phar_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/ext/phar/phar.c b/ext/phar/phar.c 2 | index 2403d77a..c908a1b4 100644 3 | --- a/ext/phar/phar.c 4 | +++ b/ext/phar/phar.c 5 | @@ -3309,6 +3309,8 @@ static zend_string *phar_resolve_path(const char *filename, size_t filename_len) 6 | return phar_find_in_include_path((char *) filename, filename_len, NULL); 7 | } 8 | 9 | +char *micro_get_filename(void); 10 | + 11 | static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) /* {{{ */ 12 | { 13 | zend_op_array *res; 14 | @@ -3319,7 +3321,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) 15 | if (!file_handle || !file_handle->filename) { 16 | return phar_orig_compile_file(file_handle, type); 17 | } 18 | - if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, "://")) { 19 | + if ((strstr(file_handle->filename, micro_get_filename()) || strstr(file_handle->filename, ".phar")) && !strstr(file_handle->filename, "://")) { 20 | if (SUCCESS == phar_open_from_filename((char*)file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL)) { 21 | if (phar->is_zip || phar->is_tar) { 22 | zend_file_handle f = *file_handle; 23 | -------------------------------------------------------------------------------- /patches/phar_81.patch: -------------------------------------------------------------------------------- 1 | diff --git a/ext/phar/phar.c b/ext/phar/phar.c 2 | index 3c0f3eb50b..455b303a8d 100644 3 | --- a/ext/phar/phar.c 4 | +++ b/ext/phar/phar.c 5 | @@ -3295,6 +3295,8 @@ static zend_string *phar_resolve_path(zend_string *filename) 6 | return ret; 7 | } 8 | 9 | +char *micro_get_filename(void); 10 | + 11 | static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) /* {{{ */ 12 | { 13 | zend_op_array *res; 14 | @@ -3305,7 +3307,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) 15 | if (!file_handle || !file_handle->filename) { 16 | return phar_orig_compile_file(file_handle, type); 17 | } 18 | - if (strstr(ZSTR_VAL(file_handle->filename), ".phar") && !strstr(ZSTR_VAL(file_handle->filename), "://")) { 19 | + if ((strstr(ZSTR_VAL(file_handle->filename), micro_get_filename()) || strstr(ZSTR_VAL(file_handle->filename), ".phar")) && !strstr(ZSTR_VAL(file_handle->filename), "://")) { 20 | if (SUCCESS == phar_open_from_filename(ZSTR_VAL(file_handle->filename), ZSTR_LEN(file_handle->filename), NULL, 0, 0, &phar, NULL)) { 21 | if (phar->is_zip || phar->is_tar) { 22 | zend_file_handle f; 23 | -------------------------------------------------------------------------------- /patches/static_extensions_win32_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/ext/fileinfo/config.w32 b/ext/fileinfo/config.w32 2 | index eefccb3d72..b231f67b23 100644 3 | --- a/ext/fileinfo/config.w32 4 | +++ b/ext/fileinfo/config.w32 5 | @@ -10,6 +10,6 @@ if (PHP_FILEINFO != 'no') { 6 | readcdf.c softmagic.c der.c \ 7 | strcasestr.c buffer.c is_csv.c"; 8 | 9 | - EXTENSION('fileinfo', 'fileinfo.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 10 | + EXTENSION('fileinfo', 'fileinfo.c', PHP_FILEINFO_SHARED, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 11 | ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo"); 12 | } 13 | diff --git a/ext/openssl/config.w32 b/ext/openssl/config.w32 14 | index 9187d6bfc2..f1acc2e8b5 100644 15 | --- a/ext/openssl/config.w32 16 | +++ b/ext/openssl/config.w32 17 | @@ -1,12 +1,12 @@ 18 | // vim:ft=javascript 19 | 20 | -ARG_WITH("openssl", "OpenSSL support", "no,shared"); 21 | +ARG_WITH("openssl", "OpenSSL support", "no"); 22 | 23 | if (PHP_OPENSSL != "no") { 24 | var ret = SETUP_OPENSSL("openssl", PHP_OPENSSL); 25 | 26 | if (ret > 0) { 27 | - EXTENSION("openssl", "openssl.c xp_ssl.c"); 28 | + EXTENSION("openssl", "openssl.c xp_ssl.c", PHP_OPENSSL_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 29 | AC_DEFINE("HAVE_OPENSSL_EXT", PHP_OPENSSL_SHARED ? 0 : 1, "Have openssl"); 30 | AC_DEFINE("HAVE_OPENSSL", 1); 31 | } 32 | -------------------------------------------------------------------------------- /patches/static_extensions_win32_83.patch: -------------------------------------------------------------------------------- 1 | diff --git a/ext/fileinfo/config.w32 b/ext/fileinfo/config.w32 2 | index e42f1ce3f7..db28a68676 100644 3 | --- a/ext/fileinfo/config.w32 4 | +++ b/ext/fileinfo/config.w32 5 | @@ -10,6 +10,6 @@ if (PHP_FILEINFO != 'no') { 6 | readcdf.c softmagic.c der.c \ 7 | strcasestr.c buffer.c is_csv.c"; 8 | 9 | - EXTENSION('fileinfo', 'fileinfo.c php_libmagic.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 10 | + EXTENSION('fileinfo', 'fileinfo.c php_libmagic.c', PHP_FILEINFO_SHARED, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 11 | ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo"); 12 | } 13 | diff --git a/ext/openssl/config.w32 b/ext/openssl/config.w32 14 | index 9187d6bfc2..f1acc2e8b5 100644 15 | --- a/ext/openssl/config.w32 16 | +++ b/ext/openssl/config.w32 17 | @@ -1,12 +1,12 @@ 18 | // vim:ft=javascript 19 | 20 | -ARG_WITH("openssl", "OpenSSL support", "no,shared"); 21 | +ARG_WITH("openssl", "OpenSSL support", "no"); 22 | 23 | if (PHP_OPENSSL != "no") { 24 | var ret = SETUP_OPENSSL("openssl", PHP_OPENSSL); 25 | 26 | if (ret > 0) { 27 | - EXTENSION("openssl", "openssl.c xp_ssl.c"); 28 | + EXTENSION("openssl", "openssl.c xp_ssl.c", PHP_OPENSSL_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 29 | AC_DEFINE("HAVE_OPENSSL_EXT", PHP_OPENSSL_SHARED ? 0 : 1, "Have openssl"); 30 | AC_DEFINE("HAVE_OPENSSL", 1); 31 | } 32 | -------------------------------------------------------------------------------- /patches/static_extensions_win32_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/ext/fileinfo/config.w32 b/ext/fileinfo/config.w32 2 | index 2a42dc45..c207694f 100644 3 | --- a/ext/fileinfo/config.w32 4 | +++ b/ext/fileinfo/config.w32 5 | @@ -10,7 +10,7 @@ if (PHP_FILEINFO != 'no') { 6 | readcdf.c softmagic.c der.c \ 7 | strcasestr.c buffer.c is_csv.c"; 8 | 9 | - EXTENSION('fileinfo', 'fileinfo.c php_libmagic.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 10 | + EXTENSION('fileinfo', 'fileinfo.c php_libmagic.c', PHP_FILEINFO_SHARED, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname); 11 | ADD_EXTENSION_DEP('fileinfo', 'pcre'); 12 | ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo"); 13 | } 14 | diff --git a/ext/openssl/config.w32 b/ext/openssl/config.w32 15 | index 24064ec2..87ff3161 100644 16 | --- a/ext/openssl/config.w32 17 | +++ b/ext/openssl/config.w32 18 | @@ -1,6 +1,6 @@ 19 | // vim:ft=javascript 20 | 21 | -ARG_WITH("openssl", "OpenSSL support", "no,shared"); 22 | +ARG_WITH("openssl", "OpenSSL support", "no"); 23 | 24 | ARG_WITH("openssl-legacy-provider", "OPENSSL: Load legacy algorithm provider in addition to default provider", "no"); 25 | 26 | @@ -10,7 +10,7 @@ if (PHP_OPENSSL != "no") { 27 | var ret = SETUP_OPENSSL("openssl", PHP_OPENSSL); 28 | 29 | if (ret >= 2) { 30 | - EXTENSION("openssl", "openssl.c openssl_pwhash.c xp_ssl.c"); 31 | + EXTENSION("openssl", "openssl.c openssl_pwhash.c xp_ssl.c", PHP_OPENSSL_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 32 | AC_DEFINE("HAVE_OPENSSL_EXT", 1, "Define to 1 if the PHP extension 'openssl' is available."); 33 | if (PHP_OPENSSL_LEGACY_PROVIDER != "no") { 34 | AC_DEFINE("LOAD_OPENSSL_LEGACY_PROVIDER", 1, "Define to 1 to load the OpenSSL legacy algorithm provider in addition to the default provider."); 35 | -------------------------------------------------------------------------------- /patches/static_opcache_80.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk 2 | index ad3781101b..b7133fc0c8 100644 3 | --- a/build/order_by_dep.awk 4 | +++ b/build/order_by_dep.awk 5 | @@ -37,6 +37,11 @@ function get_module_index(name, i) 6 | function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) 7 | { 8 | module_name = mods[mod_idx]; 9 | + # TODO: real skip zend extension 10 | + if (module_name == "opcache") { 11 | + delete mods[mod_idx]; 12 | + return; 13 | + } 14 | mod_name_len = length(module_name); 15 | 16 | for (ext in mod_deps) { 17 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 18 | index c195ad7d2c..8bb8dd78fc 100644 19 | --- a/ext/opcache/ZendAccelerator.c 20 | +++ b/ext/opcache/ZendAccelerator.c 21 | @@ -91,7 +91,10 @@ typedef int gid_t; 22 | #include 23 | #endif 24 | 25 | +#ifdef COMPILE_DL_OPCACHE 26 | +// avoid symbol conflict 27 | ZEND_EXTENSION(); 28 | +#endif 29 | 30 | #ifndef ZTS 31 | zend_accel_globals accel_globals; 32 | @@ -4991,7 +4994,11 @@ static int accel_finish_startup(void) 33 | return SUCCESS; 34 | } 35 | 36 | +#ifdef COMPILE_DL_OPCACHE 37 | ZEND_EXT_API zend_extension zend_extension_entry = { 38 | +#else 39 | +zend_extension opcache_zend_extension_entry = { 40 | +#endif 41 | ACCELERATOR_PRODUCT_NAME, /* name */ 42 | PHP_VERSION, /* version */ 43 | "Zend Technologies", /* author */ 44 | diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 45 | index 5492fd920c..6fdb475e49 100644 46 | --- a/ext/opcache/config.m4 47 | +++ b/ext/opcache/config.m4 48 | @@ -21,7 +21,8 @@ PHP_ARG_ENABLE([opcache-jit], 49 | if test "$PHP_OPCACHE" != "no"; then 50 | 51 | dnl Always build as shared extension 52 | - ext_shared=yes 53 | + dnl why? 54 | + dnl ext_shared=yes 55 | 56 | if test "$PHP_HUGE_CODE_PAGES" = "yes"; then 57 | AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) 58 | @@ -334,7 +335,9 @@ int main() { 59 | Optimizer/compact_vars.c \ 60 | Optimizer/zend_dump.c \ 61 | $ZEND_JIT_SRC, 62 | - shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes) 63 | + $ext_shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes) 64 | + 65 | + AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) 66 | 67 | PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1) 68 | PHP_ADD_EXTENSION_DEP(opcache, pcre) 69 | diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 70 | index fb921c73da..41de817bda 100644 71 | --- a/ext/opcache/config.w32 72 | +++ b/ext/opcache/config.w32 73 | @@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { 74 | zend_persist_calc.c \ 75 | zend_file_cache.c \ 76 | zend_shared_alloc.c \ 77 | - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 78 | + shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 79 | + 80 | + AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); 81 | 82 | if (PHP_OPCACHE_JIT == "yes") { 83 | if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { 84 | diff --git a/main/main.c b/main/main.c 85 | index a40a4c8c37..ae93c8ae6c 100644 86 | --- a/main/main.c 87 | +++ b/main/main.c 88 | @@ -2016,6 +2016,18 @@ void dummy_invalid_parameter_handler( 89 | } 90 | #endif 91 | 92 | +// this can be moved to other place 93 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 94 | +extern zend_extension opcache_zend_extension_entry; 95 | +extern void zend_register_extension(zend_extension *new_extension, void *handle); 96 | + 97 | +int zend_load_static_extensions(void) 98 | +{ 99 | + zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); 100 | + return 0; 101 | +} 102 | +#endif 103 | + 104 | /* {{{ php_module_startup */ 105 | int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules) 106 | { 107 | @@ -2255,6 +2267,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod 108 | ahead of all other internals 109 | */ 110 | php_ini_register_extensions(); 111 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 112 | + zend_load_static_extensions(); 113 | +#endif 114 | zend_startup_modules(); 115 | 116 | /* start Zend extensions */ 117 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 118 | index bf88cdae44..f8f6547e39 100644 119 | --- a/win32/build/confutils.js 120 | +++ b/win32/build/confutils.js 121 | @@ -1535,6 +1535,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) 122 | } 123 | } 124 | 125 | + // TODO: real skip zend extensions 126 | + if (extname != 'opcache') 127 | extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; 128 | 129 | DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); 130 | -------------------------------------------------------------------------------- /patches/static_opcache_81.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk 2 | index 1e71ea2069..3da32d8830 100644 3 | --- a/build/order_by_dep.awk 4 | +++ b/build/order_by_dep.awk 5 | @@ -37,6 +37,11 @@ function get_module_index(name, i) 6 | function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) 7 | { 8 | module_name = mods[mod_idx]; 9 | + # TODO: real skip zend extension 10 | + if (module_name == "opcache") { 11 | + delete mods[mod_idx]; 12 | + return; 13 | + } 14 | mod_name_len = length(module_name); 15 | 16 | for (ext in mod_deps) { 17 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 18 | index 5f6b854d47..ea15c0d5bc 100644 19 | --- a/ext/opcache/ZendAccelerator.c 20 | +++ b/ext/opcache/ZendAccelerator.c 21 | @@ -91,7 +91,10 @@ typedef int gid_t; 22 | #include 23 | #endif 24 | 25 | +#ifdef COMPILE_DL_OPCACHE 26 | +// avoid symbol conflict 27 | ZEND_EXTENSION(); 28 | +#endif 29 | 30 | #ifndef ZTS 31 | zend_accel_globals accel_globals; 32 | @@ -4808,7 +4811,11 @@ static int accel_finish_startup(void) 33 | return SUCCESS; 34 | } 35 | 36 | +#ifdef COMPILE_DL_OPCACHE 37 | ZEND_EXT_API zend_extension zend_extension_entry = { 38 | +#else 39 | +zend_extension opcache_zend_extension_entry = { 40 | +#endif 41 | ACCELERATOR_PRODUCT_NAME, /* name */ 42 | PHP_VERSION, /* version */ 43 | "Zend Technologies", /* author */ 44 | diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 45 | index 2a83fa2455..7b3b37182e 100644 46 | --- a/ext/opcache/config.m4 47 | +++ b/ext/opcache/config.m4 48 | @@ -21,7 +21,8 @@ PHP_ARG_ENABLE([opcache-jit], 49 | if test "$PHP_OPCACHE" != "no"; then 50 | 51 | dnl Always build as shared extension 52 | - ext_shared=yes 53 | + dnl why? 54 | + dnl ext_shared=yes 55 | 56 | if test "$PHP_HUGE_CODE_PAGES" = "yes"; then 57 | AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) 58 | @@ -327,7 +328,9 @@ int main() { 59 | shared_alloc_mmap.c \ 60 | shared_alloc_posix.c \ 61 | $ZEND_JIT_SRC, 62 | - shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 63 | + $ext_shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 64 | + 65 | + AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) 66 | 67 | PHP_ADD_EXTENSION_DEP(opcache, pcre) 68 | 69 | diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 70 | index 764a2edaab..95427090ce 100644 71 | --- a/ext/opcache/config.w32 72 | +++ b/ext/opcache/config.w32 73 | @@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { 74 | zend_persist_calc.c \ 75 | zend_file_cache.c \ 76 | zend_shared_alloc.c \ 77 | - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 78 | + shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 79 | + 80 | + AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); 81 | 82 | if (PHP_OPCACHE_JIT == "yes") { 83 | if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { 84 | diff --git a/main/main.c b/main/main.c 85 | index 8c16f01b11..0560348a06 100644 86 | --- a/main/main.c 87 | +++ b/main/main.c 88 | @@ -2011,6 +2011,18 @@ void dummy_invalid_parameter_handler( 89 | } 90 | #endif 91 | 92 | +// this can be moved to other place 93 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 94 | +extern zend_extension opcache_zend_extension_entry; 95 | +extern void zend_register_extension(zend_extension *new_extension, void *handle); 96 | + 97 | +int zend_load_static_extensions(void) 98 | +{ 99 | + zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); 100 | + return 0; 101 | +} 102 | +#endif 103 | + 104 | /* {{{ php_module_startup */ 105 | int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules) 106 | { 107 | @@ -2253,6 +2265,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod 108 | ahead of all other internals 109 | */ 110 | php_ini_register_extensions(); 111 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 112 | + zend_load_static_extensions(); 113 | +#endif 114 | zend_startup_modules(); 115 | 116 | /* start Zend extensions */ 117 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 118 | index 1a2dfe43b4..ae405f035a 100644 119 | --- a/win32/build/confutils.js 120 | +++ b/win32/build/confutils.js 121 | @@ -1535,6 +1535,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) 122 | } 123 | } 124 | 125 | + // TODO: real skip zend extensions 126 | + if (extname != 'opcache') 127 | extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; 128 | 129 | DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); 130 | -------------------------------------------------------------------------------- /patches/static_opcache_82.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk 2 | index 1e71ea20..77895167 100644 3 | --- a/build/order_by_dep.awk 4 | +++ b/build/order_by_dep.awk 5 | @@ -37,6 +37,11 @@ function get_module_index(name, i) 6 | function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) 7 | { 8 | module_name = mods[mod_idx]; 9 | + # TODO: real skip zend extension 10 | + if (module_name == "opcache") { 11 | + delete mods[mod_idx]; 12 | + return; 13 | + } 14 | mod_name_len = length(module_name); 15 | 16 | for (ext in mod_deps) { 17 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 18 | index 9bcd035c..7bc01614 100644 19 | --- a/ext/opcache/ZendAccelerator.c 20 | +++ b/ext/opcache/ZendAccelerator.c 21 | @@ -93,7 +93,10 @@ typedef int gid_t; 22 | #include 23 | #endif 24 | 25 | +#ifdef COMPILE_DL_OPCACHE 26 | +// avoid symbol conflict 27 | ZEND_EXTENSION(); 28 | +#endif 29 | 30 | #ifndef ZTS 31 | zend_accel_globals accel_globals; 32 | @@ -4792,7 +4795,11 @@ static int accel_finish_startup(void) 33 | return SUCCESS; 34 | } 35 | 36 | +#ifdef COMPILE_DL_OPCACHE 37 | ZEND_EXT_API zend_extension zend_extension_entry = { 38 | +#else 39 | +zend_extension opcache_zend_extension_entry = { 40 | +#endif 41 | ACCELERATOR_PRODUCT_NAME, /* name */ 42 | PHP_VERSION, /* version */ 43 | "Zend Technologies", /* author */ 44 | diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 45 | index b3929382..8607ff25 100644 46 | --- a/ext/opcache/config.m4 47 | +++ b/ext/opcache/config.m4 48 | @@ -21,7 +21,8 @@ PHP_ARG_ENABLE([opcache-jit], 49 | if test "$PHP_OPCACHE" != "no"; then 50 | 51 | dnl Always build as shared extension 52 | - ext_shared=yes 53 | + dnl why? 54 | + dnl ext_shared=yes 55 | 56 | if test "$PHP_HUGE_CODE_PAGES" = "yes"; then 57 | AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) 58 | @@ -336,7 +337,9 @@ int main(void) { 59 | shared_alloc_mmap.c \ 60 | shared_alloc_posix.c \ 61 | $ZEND_JIT_SRC, 62 | - shared,,"$PHP_OPCACHE_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 63 | + $ext_shared,,"$PHP_OPCACHE_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 64 | + 65 | + AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) 66 | 67 | PHP_ADD_EXTENSION_DEP(opcache, pcre) 68 | 69 | diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 70 | index 764a2eda..95427090 100644 71 | --- a/ext/opcache/config.w32 72 | +++ b/ext/opcache/config.w32 73 | @@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { 74 | zend_persist_calc.c \ 75 | zend_file_cache.c \ 76 | zend_shared_alloc.c \ 77 | - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 78 | + shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 79 | + 80 | + AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); 81 | 82 | if (PHP_OPCACHE_JIT == "yes") { 83 | if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { 84 | diff --git a/main/main.c b/main/main.c 85 | index 0adecd10..ee89ebfb 100644 86 | --- a/main/main.c 87 | +++ b/main/main.c 88 | @@ -2048,6 +2048,18 @@ void dummy_invalid_parameter_handler( 89 | } 90 | #endif 91 | 92 | +// this can be moved to other place 93 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 94 | +extern zend_extension opcache_zend_extension_entry; 95 | +extern void zend_register_extension(zend_extension *new_extension, void *handle); 96 | + 97 | +int zend_load_static_extensions(void) 98 | +{ 99 | + zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); 100 | + return 0; 101 | +} 102 | +#endif 103 | + 104 | /* {{{ php_module_startup */ 105 | zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module) 106 | { 107 | @@ -2293,6 +2305,9 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi 108 | ahead of all other internals 109 | */ 110 | php_ini_register_extensions(); 111 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 112 | + zend_load_static_extensions(); 113 | +#endif 114 | zend_startup_modules(); 115 | 116 | /* start Zend extensions */ 117 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 118 | index 4eece379..59b7bd5c 100644 119 | --- a/win32/build/confutils.js 120 | +++ b/win32/build/confutils.js 121 | @@ -1534,6 +1534,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) 122 | } 123 | } 124 | 125 | + // TODO: real skip zend extensions 126 | + if (extname != 'opcache') 127 | extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; 128 | 129 | DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); -------------------------------------------------------------------------------- /patches/static_opcache_83.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk 2 | index 1e71ea2069..3da32d8830 100644 3 | --- a/build/order_by_dep.awk 4 | +++ b/build/order_by_dep.awk 5 | @@ -37,6 +37,11 @@ function get_module_index(name, i) 6 | function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) 7 | { 8 | module_name = mods[mod_idx]; 9 | + # TODO: real skip zend extension 10 | + if (module_name == "opcache") { 11 | + delete mods[mod_idx]; 12 | + return; 13 | + } 14 | mod_name_len = length(module_name); 15 | 16 | for (ext in mod_deps) { 17 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 18 | index ec33c69eb2..b8ce7e3eca 100644 19 | --- a/ext/opcache/ZendAccelerator.c 20 | +++ b/ext/opcache/ZendAccelerator.c 21 | @@ -93,7 +93,10 @@ typedef int gid_t; 22 | #include 23 | #endif 24 | 25 | +#ifdef COMPILE_DL_OPCACHE 26 | +// avoid symbol conflict 27 | ZEND_EXTENSION(); 28 | +#endif 29 | 30 | #ifndef ZTS 31 | zend_accel_globals accel_globals; 32 | @@ -4814,7 +4817,11 @@ static int accel_finish_startup(void) 33 | #endif /* ZEND_WIN32 */ 34 | } 35 | 36 | +#ifdef COMPILE_DL_OPCACHE 37 | ZEND_EXT_API zend_extension zend_extension_entry = { 38 | +#else 39 | +zend_extension opcache_zend_extension_entry = { 40 | +#endif 41 | ACCELERATOR_PRODUCT_NAME, /* name */ 42 | PHP_VERSION, /* version */ 43 | "Zend Technologies", /* author */ 44 | diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 45 | index 2a83fa2455..7b3b37182e 100644 46 | --- a/ext/opcache/config.m4 47 | +++ b/ext/opcache/config.m4 48 | @@ -27,7 +27,8 @@ 49 | if test "$PHP_OPCACHE" != "no"; then 50 | 51 | dnl Always build as shared extension 52 | - ext_shared=yes 53 | + dnl why? 54 | + dnl ext_shared=yes 55 | 56 | if test "$PHP_HUGE_CODE_PAGES" = "yes"; then 57 | AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) 58 | @@ -319,8 +320,10 @@ 59 | shared_alloc_mmap.c \ 60 | shared_alloc_posix.c \ 61 | $ZEND_JIT_SRC, 62 | - shared,,"$PHP_OPCACHE_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 63 | + $ext_shared,,"$PHP_OPCACHE_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes) 64 | 65 | + AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) 66 | + 67 | PHP_ADD_EXTENSION_DEP(opcache, pcre) 68 | 69 | if test "$have_shm_ipc" != "yes" && test "$have_shm_mmap_posix" != "yes" && test "$have_shm_mmap_anon" != "yes"; then 70 | diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 71 | index 764a2edaab..95427090ce 100644 72 | --- a/ext/opcache/config.w32 73 | +++ b/ext/opcache/config.w32 74 | @@ -16,7 +16,9 @@ if (PHP_OPCACHE != "no") { 75 | zend_persist_calc.c \ 76 | zend_file_cache.c \ 77 | zend_shared_alloc.c \ 78 | - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 79 | + shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 80 | + 81 | + AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); 82 | 83 | if (PHP_OPCACHE_JIT == "yes") { 84 | if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { 85 | diff --git a/main/main.c b/main/main.c 86 | index 6fdfbce13e..bcccfad6e3 100644 87 | --- a/main/main.c 88 | +++ b/main/main.c 89 | @@ -2012,6 +2012,18 @@ void dummy_invalid_parameter_handler( 90 | } 91 | #endif 92 | 93 | +// this can be moved to other place 94 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 95 | +extern zend_extension opcache_zend_extension_entry; 96 | +extern void zend_register_extension(zend_extension *new_extension, void *handle); 97 | + 98 | +int zend_load_static_extensions(void) 99 | +{ 100 | + zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); 101 | + return 0; 102 | +} 103 | +#endif 104 | + 105 | /* {{{ php_module_startup */ 106 | zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module) 107 | { 108 | @@ -2196,6 +2208,9 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi 109 | ahead of all other internals 110 | */ 111 | php_ini_register_extensions(); 112 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 113 | + zend_load_static_extensions(); 114 | +#endif 115 | zend_startup_modules(); 116 | 117 | /* start Zend extensions */ 118 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 119 | index 359c751b7b..01068efcf6 100644 120 | --- a/win32/build/confutils.js 121 | +++ b/win32/build/confutils.js 122 | @@ -1534,6 +1534,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) 123 | } 124 | } 125 | 126 | + // TODO: real skip zend extensions 127 | + if (extname != 'opcache') 128 | extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; 129 | 130 | DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); 131 | -------------------------------------------------------------------------------- /patches/static_opcache_84.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build/order_by_dep.awk b/build/order_by_dep.awk 2 | index 1e71ea20..3da32d88 100644 3 | --- a/build/order_by_dep.awk 4 | +++ b/build/order_by_dep.awk 5 | @@ -37,6 +37,11 @@ function get_module_index(name, i) 6 | function do_deps(mod_idx, module_name, mod_name_len, dep, ext, val, depidx) 7 | { 8 | module_name = mods[mod_idx]; 9 | + # TODO: real skip zend extension 10 | + if (module_name == "opcache") { 11 | + delete mods[mod_idx]; 12 | + return; 13 | + } 14 | mod_name_len = length(module_name); 15 | 16 | for (ext in mod_deps) { 17 | diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c 18 | index 3e8bdea9..4a784945 100644 19 | --- a/ext/opcache/ZendAccelerator.c 20 | +++ b/ext/opcache/ZendAccelerator.c 21 | @@ -97,7 +97,10 @@ typedef int gid_t; 22 | #include 23 | #endif 24 | 25 | +#ifdef COMPILE_DL_OPCACHE 26 | +// micro: avoid symbol conflict 27 | ZEND_EXTENSION(); 28 | +#endif 29 | 30 | #ifndef ZTS 31 | zend_accel_globals accel_globals; 32 | @@ -4828,7 +4831,11 @@ static zend_result accel_finish_startup(void) 33 | #endif /* ZEND_WIN32 */ 34 | } 35 | 36 | +#ifdef COMPILE_DL_OPCACHE 37 | ZEND_EXT_API zend_extension zend_extension_entry = { 38 | +#else 39 | +zend_extension opcache_zend_extension_entry = { 40 | +#endif 41 | ACCELERATOR_PRODUCT_NAME, /* name */ 42 | PHP_VERSION, /* version */ 43 | "Zend Technologies", /* author */ 44 | diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 45 | index 8f6d5ab7..19530321 100644 46 | --- a/ext/opcache/config.m4 47 | +++ b/ext/opcache/config.m4 48 | @@ -26,8 +26,8 @@ PHP_ARG_WITH([capstone], 49 | [no]) 50 | 51 | if test "$PHP_OPCACHE" != "no"; then 52 | - dnl Always build as shared extension. 53 | - ext_shared=yes 54 | + dnl Always build as shared extension. (micro patches: no, we need static) 55 | + dnl ext_shared=yes 56 | 57 | AS_VAR_IF([PHP_HUGE_CODE_PAGES], [yes], 58 | [AC_DEFINE([HAVE_HUGE_CODE_PAGES], [1], 59 | @@ -343,6 +343,7 @@ int main(void) { 60 | [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 $JIT_CFLAGS],, 61 | [yes]) 62 | 63 | + AC_DEFINE(HAVE_OPCACHE, 1, [opcache enabled]) 64 | PHP_ADD_EXTENSION_DEP(opcache, date) 65 | PHP_ADD_EXTENSION_DEP(opcache, pcre) 66 | 67 | diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 68 | index d0af7258..a054e6c8 100644 69 | --- a/ext/opcache/config.w32 70 | +++ b/ext/opcache/config.w32 71 | @@ -16,8 +16,9 @@ if (PHP_OPCACHE != "no") { 72 | zend_persist_calc.c \ 73 | zend_file_cache.c \ 74 | zend_shared_alloc.c \ 75 | - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 76 | + shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 77 | 78 | + AC_DEFINE('HAVE_OPCACHE', 1, 'opcache enabled'); 79 | ADD_EXTENSION_DEP('opcache', 'date'); 80 | ADD_EXTENSION_DEP('opcache', 'hash'); 81 | ADD_EXTENSION_DEP('opcache', 'pcre'); 82 | diff --git a/ext/opcache/jit/ir/ir_gdb.c b/ext/opcache/jit/ir/ir_gdb.c 83 | index ecaf8803..a8275466 100644 84 | --- a/ext/opcache/jit/ir/ir_gdb.c 85 | +++ b/ext/opcache/jit/ir/ir_gdb.c 86 | @@ -504,11 +504,11 @@ typedef struct _ir_gdbjit_descriptor { 87 | extern ir_gdbjit_descriptor __jit_debug_descriptor; 88 | void __jit_debug_register_code(void); 89 | #else 90 | -ir_gdbjit_descriptor __jit_debug_descriptor = { 91 | +static ir_gdbjit_descriptor __jit_debug_descriptor = { 92 | 1, IR_GDBJIT_NOACTION, NULL, NULL 93 | }; 94 | 95 | -IR_NEVER_INLINE void __jit_debug_register_code(void) 96 | +static IR_NEVER_INLINE void __jit_debug_register_code(void) 97 | { 98 | __asm__ __volatile__(""); 99 | } 100 | diff --git a/main/main.c b/main/main.c 101 | index 0b38f303..b2cb9d4a 100644 102 | --- a/main/main.c 103 | +++ b/main/main.c 104 | @@ -2099,6 +2099,18 @@ void dummy_invalid_parameter_handler( 105 | } 106 | #endif 107 | 108 | +// this can be moved to other place 109 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 110 | +extern zend_extension opcache_zend_extension_entry; 111 | +extern void zend_register_extension(zend_extension *new_extension, void *handle); 112 | + 113 | +int zend_load_static_extensions(void) 114 | +{ 115 | + zend_register_extension(&opcache_zend_extension_entry, NULL /*opcache cannot be unloaded*/); 116 | + return 0; 117 | +} 118 | +#endif 119 | + 120 | /* {{{ php_module_startup */ 121 | zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module) 122 | { 123 | @@ -2283,6 +2295,9 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi 124 | ahead of all other internals 125 | */ 126 | php_ini_register_extensions(); 127 | +#if defined(HAVE_OPCACHE) && !defined(COMPILE_DL_OPCACHE) 128 | + zend_load_static_extensions(); 129 | +#endif 130 | zend_startup_modules(); 131 | 132 | /* start Zend extensions */ 133 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 134 | index 1a4ddbff..f47090b7 100644 135 | --- a/win32/build/confutils.js 136 | +++ b/win32/build/confutils.js 137 | @@ -1531,7 +1531,8 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir) 138 | } 139 | } 140 | } 141 | - 142 | + // micro: skip zend opcache 143 | + if (extname != 'opcache') 144 | extension_module_ptrs += '\tphpext_' + extname + '_ptr,\r\n'; 145 | 146 | DEFINE('CFLAGS_' + EXT + '_OBJ', '$(CFLAGS_PHP) $(CFLAGS_' + EXT + ')'); 147 | -------------------------------------------------------------------------------- /patches/vcruntime140_74.patch: -------------------------------------------------------------------------------- 1 | --- a/main/main.c 2020-09-29 10:17:07.000000000 +0000 2 | +++ b/main/main.c 2020-11-19 07:57:40.769785000 +0000 3 | @@ -2172,7 +2172,8 @@ int php_module_startup(sapi_module_struc 4 | #endif 5 | 6 | #ifdef PHP_WIN32 7 | -# if PHP_LINKER_MAJOR == 14 8 | +// fucked here 9 | +# if false && PHP_LINKER_MAJOR == 14 10 | /* Extend for other CRT if needed. */ 11 | # if PHP_DEBUG 12 | # define PHP_VCRUNTIME "vcruntime140d.dll" 13 | -------------------------------------------------------------------------------- /patches/vcruntime140_80.patch: -------------------------------------------------------------------------------- 1 | --- php-8.0.0-src/win32/winutil.c 2020-11-24 17:04:03.000000000 +0000 2 | +++ php-8.0.0-micro/win32/winutil.c 2020-12-03 07:59:22.177745800 +0000 3 | @@ -484,7 +484,7 @@ 4 | /* Expect a CRT module handle */ 5 | PHP_WINUTIL_API BOOL php_win32_crt_compatible(char **err) 6 | {/*{{{*/ 7 | -#if PHP_LINKER_MAJOR == 14 8 | +#if false && PHP_LINKER_MAJOR == 14 9 | /* Extend for other CRT if needed. */ 10 | # if PHP_DEBUG 11 | const char *crt_name = "vcruntime140d.dll"; 12 | -------------------------------------------------------------------------------- /patches/win32_74.patch: -------------------------------------------------------------------------------- 1 | diff -pru /mnt/c/Users/dixyes/Desktop/phiwrapaper/phibatsh/build/php-7.4.11-src/win32/build/confutils.js win32/build/confutils.js 2 | --- a/win32/build/confutils.js 2020-09-29 10:17:06.000000000 +0000 3 | +++ b/win32/build/confutils.js 2020-11-20 10:07:21.642064000 +0000 4 | @@ -3413,7 +3413,7 @@ function toolset_setup_common_libs() 5 | function toolset_setup_build_mode() 6 | { 7 | if (PHP_DEBUG == "yes") { 8 | - ADD_FLAG("CFLAGS", "/LDd /MDd /W3 /Od /D _DEBUG /D ZEND_DEBUG=1 " + 9 | + ADD_FLAG("CFLAGS", "/LDd /MTd /W3 /Od /D _DEBUG /D ZEND_DEBUG=1 " + 10 | (X64?"/Zi":"/ZI")); 11 | ADD_FLAG("LDFLAGS", "/debug"); 12 | // Avoid problems when linking to release libraries that use the release 13 | @@ -3425,7 +3425,7 @@ function toolset_setup_build_mode() 14 | ADD_FLAG("CFLAGS", "/Zi"); 15 | ADD_FLAG("LDFLAGS", "/incremental:no /debug /opt:ref,icf"); 16 | } 17 | - ADD_FLAG("CFLAGS", "/LD /MD /W3"); 18 | + ADD_FLAG("CFLAGS", "/LD /MT /W3"); 19 | if (PHP_SANITIZER == "yes" && CLANG_TOOLSET) { 20 | ADD_FLAG("CFLAGS", "/Od /D NDebug /D NDEBUG /D ZEND_WIN32_NEVER_INLINE /D ZEND_DEBUG=0"); 21 | } else { 22 | -------------------------------------------------------------------------------- /patches/win32_80.patch: -------------------------------------------------------------------------------- 1 | diff -urN php-8.0.0-src/win32/build/confutils.js php-8.0.0-micro/win32/build/confutils.js 2 | --- php-8.0.0-src/win32/build/confutils.js 2020-11-24 17:04:03.000000000 +0000 3 | +++ php-8.0.0-micro/win32/build/confutils.js 2020-12-03 06:16:12.949921700 +0000 4 | @@ -3407,7 +3407,7 @@ 5 | function toolset_setup_build_mode() 6 | { 7 | if (PHP_DEBUG == "yes") { 8 | - ADD_FLAG("CFLAGS", "/LDd /MDd /Od /D _DEBUG /D ZEND_DEBUG=1 " + 9 | + ADD_FLAG("CFLAGS", "/LDd /MTd /Od /D _DEBUG /D ZEND_DEBUG=1 " + 10 | (X64?"/Zi":"/ZI")); 11 | ADD_FLAG("LDFLAGS", "/debug"); 12 | // Avoid problems when linking to release libraries that use the release 13 | @@ -3419,7 +3419,7 @@ 14 | ADD_FLAG("CFLAGS", "/Zi"); 15 | ADD_FLAG("LDFLAGS", "/incremental:no /debug /opt:ref,icf"); 16 | } 17 | - ADD_FLAG("CFLAGS", "/LD /MD"); 18 | + ADD_FLAG("CFLAGS", "/LD /MT"); 19 | if (PHP_SANITIZER == "yes" && CLANG_TOOLSET) { 20 | ADD_FLAG("CFLAGS", "/Od /D NDebug /D NDEBUG /D ZEND_WIN32_NEVER_INLINE /D ZEND_DEBUG=0"); 21 | } else { 22 | -------------------------------------------------------------------------------- /patches/win32_82.patch: -------------------------------------------------------------------------------- 1 | diff --git a/win32/build/confutils.js b/win32/build/confutils.js 2 | index dc6675c6d2..587d4022a6 100644 3 | --- a/win32/build/confutils.js 4 | +++ b/win32/build/confutils.js 5 | @@ -3454,7 +3454,7 @@ function toolset_setup_common_libs() 6 | function toolset_setup_build_mode() 7 | { 8 | if (PHP_DEBUG == "yes") { 9 | - ADD_FLAG("CFLAGS", "/LDd /MDd /Od /D _DEBUG /D ZEND_DEBUG=1 " + 10 | + ADD_FLAG("CFLAGS", "/LDd /MTd /Od /D _DEBUG /D ZEND_DEBUG=1 " + 11 | (TARGET_ARCH == 'x86'?"/ZI":"/Zi")); 12 | ADD_FLAG("LDFLAGS", "/debug"); 13 | // Avoid problems when linking to release libraries that use the release 14 | @@ -3466,7 +3466,7 @@ function toolset_setup_build_mode() 15 | ADD_FLAG("CFLAGS", "/Zi"); 16 | ADD_FLAG("LDFLAGS", "/incremental:no /debug /opt:ref,icf"); 17 | } 18 | - ADD_FLAG("CFLAGS", "/LD /MD"); 19 | + ADD_FLAG("CFLAGS", "/LD /MT"); 20 | if (PHP_SANITIZER == "yes" && CLANG_TOOLSET) { 21 | ADD_FLAG("CFLAGS", "/Od /D NDebug /D NDEBUG /D ZEND_WIN32_NEVER_INLINE /D ZEND_DEBUG=0"); 22 | } else { 23 | -------------------------------------------------------------------------------- /patches/zend_stream.patch: -------------------------------------------------------------------------------- 1 | --- php-8.0.0-src/Zend/zend_stream.c 2020-11-24 17:04:03.000000000 +0000 2 | +++ php-8.0.0-micro/Zend/zend_stream.c 2020-12-03 07:01:36.375355300 +0000 3 | @@ -23,7 +23,9 @@ 4 | #include "zend_compile.h" 5 | #include "zend_stream.h" 6 | 7 | +#if !defined(_CRT_INTERNAL_NONSTDC_NAMES) || !_CRT_INTERNAL_NONSTDC_NAMES 8 | ZEND_DLIMPORT int isatty(int fd); 9 | +#endif 10 | 11 | static ssize_t zend_stream_stdio_reader(void *handle, char *buf, size_t len) /* {{{ */ 12 | { 13 | -------------------------------------------------------------------------------- /php_micro.c: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro.c 3 | main file for micro sapi 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | this file contains source from php 21 | here's original copyright notice 22 | +----------------------------------------------------------------------+ 23 | | Copyright (c) The PHP Group | 24 | +----------------------------------------------------------------------+ 25 | | This source file is subject to version 3.01 of the PHP license, | 26 | | that is bundled with this package in the file LICENSE, and is | 27 | | available through the world-wide-web at the following url: | 28 | | https://www.php.net/license/3_01.txt | 29 | | If you did not receive a copy of the PHP license and are unable to | 30 | | obtain it through the world-wide-web, please send a note to | 31 | | license@php.net so we can mail you a copy immediately. | 32 | +----------------------------------------------------------------------+ 33 | | Author: Edin Kadribasic | 34 | | Marcus Boerger | 35 | | Johannes Schlueter | 36 | | Parts based on CGI SAPI Module by | 37 | | Rasmus Lerdorf, Stig Bakken and Zeev Suraski | 38 | +----------------------------------------------------------------------+ 39 | */ 40 | 41 | #include "php.h" 42 | #include "php_globals.h" 43 | #include "php_main.h" 44 | #include "php_variables.h" 45 | 46 | #ifdef PHP_WIN32 47 | # include "win32/console.h" 48 | # include "win32/ioutil.h" 49 | # include "win32/select.h" 50 | # include "win32/signal.h" 51 | # include "win32/time.h" 52 | BOOL php_win32_init_random_bytes(void); 53 | BOOL php_win32_shutdown_random_bytes(void); 54 | BOOL php_win32_ioutil_init(void); 55 | #if PHP_VERSION_ID < 80400 56 | void php_win32_init_gettimeofday(void); 57 | #endif 58 | #else 59 | # define php_select(m, r, w, e, t) select(m, r, w, e, t) 60 | # include 61 | # include 62 | #endif 63 | 64 | #include "ext/standard/php_standard.h" 65 | #include "sapi/cli/php_cli_process_title.h" 66 | #include "sapi/cli/ps_title.h" 67 | #if PHP_VERSION_ID >= 80000 68 | # include "sapi/cli/php_cli_process_title_arginfo.h" 69 | #endif 70 | 71 | #include "SAPI.h" 72 | 73 | #include "php_micro.h" 74 | #include "php_micro_fileinfo.h" 75 | #include "php_micro_helper.h" 76 | #include "php_micro_hooks.h" 77 | 78 | const char HARDCODED_INI[] = "html_errors=0\n" 79 | "register_argc_argv=1\n" 80 | "implicit_flush=1\n" 81 | "output_buffering=0\n" 82 | "max_execution_time=0\n" 83 | "max_input_time=-1\n\0"; 84 | 85 | static inline bool sapi_micro_select(php_socket_t fd) { 86 | fd_set wfd; 87 | struct timeval tv; 88 | int ret; 89 | 90 | FD_ZERO(&wfd); 91 | 92 | PHP_SAFE_FD_SET(fd, &wfd); 93 | 94 | tv.tv_sec = (long)FG(default_socket_timeout); 95 | tv.tv_usec = 0; 96 | 97 | ret = php_select(fd + 1, NULL, &wfd, NULL, &tv); 98 | 99 | return ret != -1; 100 | } 101 | 102 | static ssize_t sapi_micro_single_write(const char *str, size_t str_length) /* {{{ */ 103 | { 104 | ssize_t ret; 105 | 106 | /* TODO: support shell callbacks 107 | if (cli_shell_callbacks.cli_shell_write) { 108 | cli_shell_callbacks.cli_shell_write(str, str_length); 109 | } 110 | */ 111 | 112 | #ifdef PHP_WRITE_STDOUT 113 | do { 114 | ret = write(STDOUT_FILENO, str, str_length); 115 | } while (ret <= 0 && (errno == EINTR || (errno == EAGAIN && sapi_micro_select(STDOUT_FILENO)))); 116 | #else 117 | ret = fwrite(str, 1, MIN(str_length, 16384), stdout); 118 | if (ret == 0 && ferror(stdout)) { 119 | return -1; 120 | } 121 | #endif 122 | return ret; 123 | } 124 | /* }}} */ 125 | 126 | static size_t sapi_micro_ub_write(const char *str, size_t str_length) /* {{{ */ 127 | { 128 | const char *ptr = str; 129 | size_t remaining = str_length; 130 | ssize_t ret; 131 | 132 | if (!str_length) { 133 | return 0; 134 | } 135 | /* todo: support shell callbacks 136 | if (cli_shell_callbacks.cli_shell_ub_write) { 137 | size_t ub_wrote; 138 | ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length); 139 | if (ub_wrote != (size_t) -1) { 140 | return ub_wrote; 141 | } 142 | } 143 | */ 144 | 145 | while (remaining > 0) { 146 | ret = sapi_micro_single_write(ptr, remaining); 147 | if (ret < 0) { 148 | #ifndef PHP_CLI_WIN32_NO_CONSOLE 149 | EG(exit_status) = 255; 150 | php_handle_aborted_connection(); 151 | #endif 152 | break; 153 | } 154 | ptr += ret; 155 | remaining -= ret; 156 | } 157 | 158 | return (ptr - str); 159 | } 160 | /* }}} */ 161 | 162 | static void sapi_micro_flush(void *server_context) /* {{{ */ 163 | { 164 | /* Ignore EBADF here, it's caused by the fact that STDIN/STDOUT/STDERR streams 165 | * are/could be closed before fflush() is called. 166 | */ 167 | if (fflush(stdout) == EOF && errno != EBADF) { 168 | #ifndef PHP_MICRO_WIN32_NO_CONSOLE 169 | php_handle_aborted_connection(); 170 | #endif 171 | } 172 | } 173 | /* }}} */ 174 | 175 | static char *php_self = ""; 176 | static char *script_filename = ""; 177 | 178 | static void sapi_micro_register_variables(zval *track_vars_array) /* {{{ */ 179 | { 180 | size_t len; 181 | char *docroot = ""; 182 | 183 | /* In CGI mode, we consider the environment to be a part of the server 184 | * variables 185 | */ 186 | php_import_environment_variables(track_vars_array); 187 | 188 | /* Build the special-case PHP_SELF variable for the CLI version */ 189 | len = strlen(php_self); 190 | if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, len, &len)) { 191 | php_register_variable("PHP_SELF", php_self, track_vars_array); 192 | } 193 | if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &php_self, len, &len)) { 194 | php_register_variable("SCRIPT_NAME", php_self, track_vars_array); 195 | } 196 | /* filenames are empty for stdin */ 197 | len = strlen(script_filename); 198 | if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &script_filename, len, &len)) { 199 | php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array); 200 | } 201 | if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &script_filename, len, &len)) { 202 | php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array); 203 | } 204 | /* just make it available */ 205 | len = 0U; 206 | if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len)) { 207 | php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array); 208 | } 209 | } 210 | /* }}} */ 211 | 212 | static void sapi_micro_log_message(const char *message, int syslog_type_int) /* {{{ */ 213 | { 214 | fprintf(stderr, "%s\n", message); 215 | #ifdef PHP_WIN32 216 | fflush(stderr); 217 | #endif 218 | } 219 | /* }}} */ 220 | 221 | static int sapi_micro_deactivate(void) /* {{{ */ 222 | { 223 | fflush(stdout); 224 | if (SG(request_info).argv0) { 225 | free(SG(request_info).argv0); 226 | SG(request_info).argv0 = NULL; 227 | } 228 | return SUCCESS; 229 | } 230 | /* }}} */ 231 | 232 | static char *sapi_micro_read_cookies(void) /* {{{ */ 233 | { 234 | return NULL; 235 | } 236 | /* }}} */ 237 | 238 | static int sapi_micro_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s) /* {{{ */ 239 | { 240 | return 0; 241 | } 242 | /* }}} */ 243 | 244 | static int sapi_micro_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */ 245 | { 246 | /* We do nothing here, this function is needed to prevent that the fallback 247 | * header handling is called. */ 248 | return SAPI_HEADER_SENT_SUCCESSFULLY; 249 | } 250 | /* }}} */ 251 | 252 | static void sapi_micro_send_header(sapi_header_struct *sapi_header, void *server_context) /* {{{ */ 253 | { 254 | } 255 | /* }}} */ 256 | 257 | int micro_register_post_startup_cb(void); 258 | 259 | static int php_micro_startup(sapi_module_struct *sapi_module) /* {{{ */ 260 | { 261 | micro_register_post_startup_cb(); 262 | 263 | #if PHP_VERSION_ID >= 80200 264 | return php_module_startup(sapi_module, NULL); 265 | #else 266 | return php_module_startup(sapi_module, NULL, 0); 267 | #endif 268 | } 269 | 270 | int php_micro_module_shutdown_wrapper(sapi_module_struct *sapi_globals) { 271 | php_module_shutdown(); 272 | return SUCCESS; 273 | } 274 | 275 | /* overwritable ini defaults must be set in sapi_micro_ini_defaults() */ 276 | #define INI_DEFAULT(name, value) \ 277 | ZVAL_NEW_STR(&tmp, zend_string_init(value, sizeof(value) - 1, 1)); \ 278 | zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp); 279 | 280 | /* 281 | * sapi_micro_ini_defaults - set overwriteable ini defaults 282 | */ 283 | static void sapi_micro_ini_defaults(HashTable *configuration_hash) { 284 | zval tmp; 285 | // INI_DEFAULT("report_zend_debug", "0"); 286 | INI_DEFAULT("display_errors", "1"); 287 | #undef INI_DEFAULT 288 | 289 | // omit PG(php_binary) before any php_ini codes used it 290 | if (NULL != PG(php_binary)) { 291 | free(PG(php_binary)); 292 | PG(php_binary) = NULL; 293 | } 294 | } 295 | 296 | /* {{{ sapi_module_struct micro_sapi_module 297 | */ 298 | static sapi_module_struct micro_sapi_module = { 299 | #ifdef PHP_MICRO_FAKE_CLI 300 | "cli", /* name */ 301 | #else 302 | "micro", /* name */ 303 | #endif 304 | "micro PHP sfx", /* pretty name */ 305 | 306 | php_micro_startup, /* startup */ 307 | php_micro_module_shutdown_wrapper, /* shutdown */ 308 | 309 | NULL, /* activate */ 310 | sapi_micro_deactivate, /* deactivate */ 311 | 312 | sapi_micro_ub_write, /* unbuffered write */ 313 | sapi_micro_flush, /* flush */ 314 | 315 | NULL, /* get uid */ 316 | NULL, /* getenv */ 317 | 318 | php_error, /* error handler */ 319 | 320 | sapi_micro_header_handler, /* header handler */ 321 | sapi_micro_send_headers, /* send headers handler */ 322 | sapi_micro_send_header, /* send header handler */ 323 | 324 | NULL, /* read POST data */ 325 | sapi_micro_read_cookies, /* read Cookies */ 326 | 327 | sapi_micro_register_variables, /* register server variables */ 328 | sapi_micro_log_message, /* Log message */ 329 | 330 | NULL, /* Get request time */ 331 | NULL, /* Child terminate */ 332 | 333 | STANDARD_SAPI_MODULE_PROPERTIES, 334 | }; 335 | /* }}} */ 336 | 337 | #ifdef _DEBUG 338 | 339 | ZEND_BEGIN_ARG_INFO(arginfo_dl, 0) 340 | ZEND_ARG_INFO(0, extension_filename) 341 | ZEND_END_ARG_INFO() 342 | ZEND_BEGIN_ARG_INFO(arginfo_micro_update_extension_dir, 0) 343 | ZEND_ARG_INFO(0, new_dir) 344 | ZEND_END_ARG_INFO() 345 | 346 | # ifdef PHP_WIN32 347 | ZEND_BEGIN_ARG_INFO(arginfo_micro_enum_modules, 0) 348 | ZEND_END_ARG_INFO() 349 | 350 | # endif // PHP_WIN32 351 | 352 | #endif 353 | 354 | ZEND_BEGIN_ARG_INFO(arginfo_micro_get_sfx_filesize, 0) 355 | ZEND_END_ARG_INFO() 356 | 357 | ZEND_BEGIN_ARG_INFO(arginfo_micro_get_sfxsize, 0) 358 | ZEND_END_ARG_INFO() 359 | 360 | ZEND_BEGIN_ARG_INFO(arginfo_micro_get_sfxsize_limit, 0) 361 | ZEND_END_ARG_INFO() 362 | 363 | ZEND_BEGIN_ARG_INFO(arginfo_micro_get_self_filename, 0) 364 | ZEND_END_ARG_INFO() 365 | 366 | ZEND_BEGIN_ARG_INFO(arginfo_micro_version, 0) 367 | ZEND_END_ARG_INFO() 368 | 369 | ZEND_BEGIN_ARG_INFO(arginfo_micro_open_self, 0) 370 | ZEND_END_ARG_INFO() 371 | 372 | // clang-format off 373 | 374 | #ifdef PHP_WIN32 375 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_realloc_console, 0, 0, _IS_BOOL, 0) 376 | ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, alloc, _IS_BOOL, 0, "false") 377 | ZEND_END_ARG_INFO() 378 | #endif // PHP_WIN32 379 | 380 | static const zend_function_entry additional_functions[] = { 381 | #ifdef _DEBUG 382 | // debug functions 383 | ZEND_FE(dl, arginfo_dl) 384 | PHP_FE(micro_update_extension_dir, arginfo_micro_update_extension_dir) 385 | # ifdef PHP_WIN32 386 | PHP_FE(micro_enum_modules, arginfo_micro_enum_modules) 387 | # endif // PHP_WIN32 388 | #endif // _DEBUG 389 | // cli functions 390 | PHP_FE(cli_set_process_title, arginfo_cli_set_process_title) 391 | PHP_FE(cli_get_process_title, arginfo_cli_get_process_title) 392 | // micro sapi functions 393 | PHP_FE(micro_get_sfx_filesize, arginfo_micro_get_sfx_filesize) 394 | PHP_FE(micro_get_sfxsize, arginfo_micro_get_sfxsize) 395 | PHP_FE(micro_get_sfxsize_limit, arginfo_micro_get_sfxsize_limit) 396 | PHP_FE(micro_get_self_filename, arginfo_micro_get_self_filename) 397 | PHP_FE(micro_version, arginfo_micro_version) 398 | PHP_FE(micro_open_self, arginfo_micro_open_self) 399 | #ifdef PHP_WIN32 400 | PHP_FE(realloc_console, arginfo_realloc_console) 401 | #endif // PHP_WIN32 402 | PHP_FE_END 403 | }; 404 | 405 | // clang-format on 406 | 407 | // static php_stream *s_in_process = NULL; 408 | 409 | static void micro_register_file_handles(void) /* {{{ */ 410 | { 411 | php_stream *s_in, *s_out, *s_err; 412 | php_stream_context *sc_in = NULL, *sc_out = NULL, *sc_err = NULL; 413 | zend_constant ic, oc, ec; 414 | 415 | s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in); 416 | s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); 417 | s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); 418 | 419 | /* Release stream resources, but don't free the underlying handles. Otherwise, 420 | * extensions which write to stderr or company during mshutdown/gshutdown 421 | * won't have the expected functionality. 422 | */ 423 | #if PHP_VERSION_ID >= 80200 424 | if (s_in) 425 | s_in->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; 426 | if (s_out) 427 | s_out->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; 428 | if (s_err) 429 | s_err->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; 430 | #else 431 | if (s_in) 432 | s_in->flags |= PHP_STREAM_FLAG_NO_CLOSE; 433 | if (s_out) 434 | s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; 435 | if (s_err) 436 | s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; 437 | #endif // PHP_VERSION_ID >= 80200 438 | 439 | if (s_in == NULL || s_out == NULL || s_err == NULL) { 440 | if (s_in) 441 | php_stream_close(s_in); 442 | if (s_out) 443 | php_stream_close(s_out); 444 | if (s_err) 445 | php_stream_close(s_err); 446 | return; 447 | } 448 | 449 | // not used 450 | // s_in_process = s_in; 451 | 452 | php_stream_to_zval(s_in, &ic.value); 453 | php_stream_to_zval(s_out, &oc.value); 454 | php_stream_to_zval(s_err, &ec.value); 455 | 456 | #if PHP_VERSION_ID >= 80300 457 | Z_CONSTANT_FLAGS(ic.value) = 0; 458 | #else 459 | ZEND_CONSTANT_SET_FLAGS(&ic, CONST_CS, 0); 460 | #endif // PHP_VERSION_ID >= 80300 461 | ic.name = zend_string_init_interned("STDIN", sizeof("STDIN") - 1, 0); 462 | zend_register_constant(&ic); 463 | 464 | #if PHP_VERSION_ID >= 80300 465 | Z_CONSTANT_FLAGS(oc.value) = 0; 466 | #else 467 | ZEND_CONSTANT_SET_FLAGS(&oc, CONST_CS, 0); 468 | #endif // PHP_VERSION_ID >= 80300 469 | oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT") - 1, 0); 470 | zend_register_constant(&oc); 471 | 472 | #if PHP_VERSION_ID >= 80300 473 | Z_CONSTANT_FLAGS(ec.value) = 0; 474 | #else 475 | ZEND_CONSTANT_SET_FLAGS(&ec, CONST_CS, 0); 476 | #endif // PHP_VERSION_ID >= 80300 477 | ec.name = zend_string_init_interned("STDERR", sizeof("STDERR") - 1, 0); 478 | zend_register_constant(&ec); 479 | } 480 | /* }}} */ 481 | 482 | #ifdef _DEBUG 483 | int micro_debug = 0; 484 | #endif 485 | /* {{{ main 486 | */ 487 | #ifdef PHP_MICRO_WIN32_NO_CONSOLE 488 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 489 | #else 490 | int main(int argc, char *argv[]) 491 | #endif 492 | { 493 | 494 | #ifdef PHP_MICRO_WIN32_NO_CONSOLE 495 | int argc = __argc; 496 | char **argv = __argv; 497 | #endif 498 | 499 | int exit_status = 0; 500 | #ifdef _DEBUG 501 | const char *_debug_env = getenv("MICRO_DEBUG"); 502 | micro_debug = _debug_env && (int)strnlen(_debug_env, 1); 503 | #endif 504 | #if defined(PHP_WIN32) && defined(_DEBUG) 505 | if (0 != (exit_status = micro_helper_init())) { 506 | return exit_status; 507 | } 508 | #endif 509 | if (0 != (exit_status = micro_fileinfo_init())) { 510 | return exit_status; 511 | } 512 | const size_t sfxsize = micro_get_sfxsize(); 513 | dbgprintf("my final sfxsize is %zd\n", sfxsize); 514 | zend_file_handle file_handle; 515 | const char *self_filename_mb = micro_get_filename(); 516 | php_self = (char *)micro_get_filename(); 517 | script_filename = (char *)micro_get_filename(); 518 | dbgprintf("self is %s\n", self_filename_mb); 519 | 520 | /* 521 | * Do not move this initialization. It needs to happen before argv is used 522 | * in any way. 523 | */ 524 | argv = save_ps_args(argc, argv); 525 | 526 | char *translated_path; 527 | // prepare our ini entries with stub 528 | char *ini_entries = malloc(sizeof(HARDCODED_INI) + micro_ext_ini.size); 529 | memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI)); 530 | size_t ini_entries_len = sizeof(HARDCODED_INI); 531 | if (0 < micro_ext_ini.size) { 532 | memcpy(&ini_entries[ini_entries_len - 2], micro_ext_ini.data, micro_ext_ini.size); 533 | ini_entries_len += micro_ext_ini.size - 2; 534 | free(micro_ext_ini.data); 535 | micro_ext_ini.data = NULL; 536 | } 537 | // remove ending 2 '\0's 538 | ini_entries_len -= 2; 539 | 540 | sapi_module_struct *sapi_module = µ_sapi_module; 541 | int module_started = 0, request_started = 0, sapi_started = 0; 542 | 543 | #if defined(PHP_WIN32) && !defined(PHP_MICRO_WIN32_NO_CONSOLE) 544 | php_win32_console_fileno_set_vt100(STDOUT_FILENO, TRUE); 545 | php_win32_console_fileno_set_vt100(STDERR_FILENO, TRUE); 546 | #endif 547 | 548 | micro_sapi_module.additional_functions = additional_functions; 549 | 550 | #if false && defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP) 551 | { 552 | char *tmp = getenv("PHP_WIN32_DEBUG_HEAP"); 553 | if (tmp && ZEND_ATOL(tmp)) { 554 | int tmp_flag; 555 | _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 556 | _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 557 | _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 558 | _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); 559 | _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 560 | _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); 561 | tmp_flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 562 | tmp_flag |= _CRTDBG_DELAY_FREE_MEM_DF; 563 | tmp_flag |= _CRTDBG_LEAK_CHECK_DF; 564 | 565 | _CrtSetDbgFlag(tmp_flag); 566 | } 567 | } 568 | #endif 569 | 570 | #if defined(SIGPIPE) && defined(SIG_IGN) 571 | signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so 572 | that sockets created via fsockopen() 573 | don't kill PHP if the remote site 574 | closes it. in apache|apxs mode apache 575 | does that for us! thies@thieso.net 576 | 20000419 */ 577 | #endif 578 | 579 | #ifdef ZTS 580 | php_tsrm_startup(); 581 | # ifdef PHP_WIN32 582 | ZEND_TSRMLS_CACHE_UPDATE(); 583 | # endif 584 | #endif 585 | 586 | zend_signal_startup(); 587 | 588 | #ifdef PHP_WIN32 589 | int wapiret = 0; 590 | php_win32_init_random_bytes(); 591 | // php_win32_signal_ctrl_handler_init(); 592 | php_win32_ioutil_init(); 593 | #if PHP_VERSION_ID < 80400 594 | php_win32_init_gettimeofday(); 595 | #endif 596 | 597 | _fmode = _O_BINARY; /* sets default for file streams to binary */ 598 | setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ 599 | setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ 600 | setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ 601 | #endif 602 | 603 | // here we start execution 604 | dbgprintf("start try catch\n"); 605 | zend_first_try { 606 | sapi_module->ini_defaults = sapi_micro_ini_defaults; 607 | // this should not be settable 608 | // TODO: macro to configure or special things 609 | // sapi_module->php_ini_path_override = ini_path_override; 610 | sapi_module->phpinfo_as_text = 1; 611 | sapi_module->php_ini_ignore_cwd = 1; 612 | sapi_module->php_ini_ignore = 1; 613 | dbgprintf("start sapi\n"); 614 | sapi_startup(sapi_module); 615 | sapi_started = 1; 616 | 617 | sapi_module->executable_location = argv[0]; 618 | sapi_module->ini_entries = ini_entries; 619 | 620 | /* startup after we get the above ini override se we get things right */ 621 | dbgprintf("start minit\n"); 622 | if (sapi_module->startup(sapi_module) == FAILURE) { 623 | dbgprintf("failed minit\n"); 624 | exit_status = 1; 625 | goto out; 626 | } 627 | 628 | // omit PHP_BINARY constant 629 | // or let PHP_BINARY constant <- micro.php_binary if setted in ini 630 | zend_constant *pbconstant = NULL; 631 | if (NULL != 632 | (pbconstant = (zend_constant *)zend_hash_str_find_ptr( 633 | EG(zend_constants), "PHP_BINARY", sizeof("PHP_BINARY") - 1))) { 634 | dbgprintf("remake pb constant %s\n", Z_STRVAL(pbconstant->value)); 635 | zend_ini_entry *pbentry = NULL; 636 | if (NULL != 637 | (pbentry = zend_hash_str_find_ptr( 638 | EG(ini_directives), PHP_MICRO_INIENTRY(php_binary), sizeof(PHP_MICRO_INIENTRY(php_binary)) - 1))) { 639 | dbgprintf("to \"%s\" [%lu]\n", ZSTR_VAL(pbentry->value), ZSTR_LEN(pbentry->value)); 640 | 641 | ZVAL_STR_COPY(&pbconstant->value, pbentry->value); 642 | } else { 643 | dbgprintf("removed\n"); 644 | ZVAL_STRINGL(&pbconstant->value, "", 0); 645 | } 646 | } 647 | /* 648 | if (SUCCESS != (exit_status = micro_open_self_stream())){ 649 | goto out; 650 | } 651 | */ 652 | 653 | module_started = 1; 654 | 655 | // hook at here for some extensions that will modify standard ops 656 | if (SUCCESS != (exit_status = micro_hook_plain_files_wops())) { 657 | // if hook failed, go error 658 | goto out; 659 | } 660 | 661 | // use module storage 662 | zend_interned_strings_switch_storage(0); 663 | // hook at here for some extensions that will register proto 664 | // TODO: zip 665 | // if (SUCCESS != (exit_status = micro_reregister_proto("phar"))) { 666 | // // if hook failed, go error 667 | // goto out; 668 | // } 669 | // switch back 670 | zend_interned_strings_switch_storage(1); 671 | 672 | FILE *fp = VCWD_FOPEN(self_filename_mb, "rb"); 673 | 674 | dbgprintf("fin opening self\n"); 675 | if (!fp) { 676 | dbgprintf("Could not open self.\n"); 677 | goto err; 678 | } 679 | 680 | // no chdir as cli do 681 | SG(options) |= SAPI_OPTION_NO_CHDIR; 682 | 683 | zend_stream_init_fp(&file_handle, fp, self_filename_mb); 684 | micro_hook_file_handle(&file_handle); 685 | #if PHP_VERSION_ID >= 80100 686 | file_handle.primary_script = 1; 687 | #endif // PHP_VERSION_ID >= 80100 688 | 689 | dbgprintf("set args\n"); 690 | SG(request_info).argc = argc; 691 | char real_path[MAXPATHLEN]; 692 | if (VCWD_REALPATH(self_filename_mb, real_path)) { 693 | translated_path = strdup(real_path); 694 | } 695 | SG(request_info).path_translated = translated_path; // tofree 696 | SG(request_info).argv = argv; 697 | 698 | dbgprintf("start rinit\n"); 699 | if (php_request_startup() == FAILURE) { 700 | fclose(file_handle.handle.fp); 701 | dbgprintf("failed rinit\n"); 702 | goto err; 703 | } 704 | dbgprintf("done rinit\n"); 705 | request_started = 1; 706 | 707 | // add STD{OUT, IN, ERR} constants 708 | micro_register_file_handles(); 709 | CG(skip_shebang) = 1; 710 | zend_register_bool_constant( 711 | ZEND_STRL("PHP_CLI_PROCESS_TITLE"), is_ps_title_available() == PS_TITLE_SUCCESS, CONST_CS, 0); 712 | 713 | // ? 714 | #if PHP_VERSION_ID >= 80100 715 | zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER)); 716 | #else 717 | zend_is_auto_global_str(ZEND_STRL("_SERVER")); 718 | #endif 719 | 720 | PG(during_request_startup) = 0; 721 | 722 | dbgprintf("start execution\n"); 723 | php_execute_script(&file_handle); 724 | exit_status = EG(exit_status); 725 | } 726 | zend_end_try(); 727 | 728 | out: 729 | // frees here 730 | if (file_handle.filename) { 731 | zend_destroy_file_handle(&file_handle); 732 | } 733 | if (request_started) { 734 | dbgprintf("rshutdown\n"); 735 | php_request_shutdown((void *)0); 736 | } 737 | if (translated_path) { 738 | free(translated_path); 739 | } 740 | if (exit_status == 0) { 741 | exit_status = EG(exit_status); 742 | } 743 | if (ini_entries) { 744 | free(ini_entries); 745 | } 746 | // micro_free_reregistered_protos(); 747 | if (module_started) { 748 | dbgprintf("mshutdown\n"); 749 | php_module_shutdown(); 750 | } 751 | if (sapi_started) { 752 | dbgprintf("sapishutdown\n"); 753 | sapi_shutdown(); 754 | } 755 | #ifdef ZTS 756 | dbgprintf("tsrmshutdown\n"); 757 | tsrm_shutdown(); 758 | #endif 759 | cleanup_ps_args(argv); 760 | return exit_status; 761 | err: 762 | sapi_deactivate(); 763 | zend_ini_deactivate(); 764 | exit_status = 1; 765 | goto out; 766 | 767 | // never reach here 768 | return 0; 769 | } 770 | /* }}} */ 771 | -------------------------------------------------------------------------------- /php_micro.h: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro.h 3 | header for micro 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | #ifndef _PHP_MICRO_H 21 | #define _PHP_MICRO_H 22 | 23 | #define STRINGIZE(x) STRINGIZE2(x) 24 | #define STRINGIZE2(x) #x 25 | 26 | #define PHP_MICRO_VER_MAJ 0 27 | #define PHP_MICRO_VER_MIN 2 28 | #define PHP_MICRO_VER_PAT 0 29 | // #define PHP_MICRO_VER_APP "nope" 30 | #ifdef PHP_MICRO_VER_APP 31 | # define PHP_MICRO_VER_STR \ 32 | STRINGIZE(PHP_MICRO_VER_MAJ) "." STRINGIZE(PHP_MICRO_VER_MIN) "." STRINGIZE(PHP_MICRO_VER_PAT) "-" PHP_MICRO_VER_APP 33 | #else 34 | # define PHP_MICRO_VER_STR \ 35 | STRINGIZE(PHP_MICRO_VER_MAJ) "." STRINGIZE(PHP_MICRO_VER_MIN) "." STRINGIZE(PHP_MICRO_VER_PAT) 36 | #endif 37 | 38 | #define PHP_MICRO_SFXSIZE_ID 12345 39 | #ifdef PHP_WIN32 40 | # define PHP_MICRO_HINT_CMDC "copy /b %s + mycode.php mycode.exe" 41 | # define PHP_MICRO_HINT_CMDE "mycode.exe myarg1 myarg2" 42 | #else 43 | # define PHP_MICRO_HINT_CMDC "cat %s mycode.php > mycode && chmod 0755 ./mycode" 44 | # define PHP_MICRO_HINT_CMDE "./mycode myarg1 myarg2" 45 | #endif 46 | #define PHP_MICRO_HINT \ 47 | "micro SAPI for PHP" PHP_VERSION " v" PHP_MICRO_VER_STR "\n" \ 48 | "Usage: concatenate this binary with any php code then execute it.\n" \ 49 | "for example: if we have code as mycode.php, to concatenate them, execute:\n" \ 50 | " " PHP_MICRO_HINT_CMDC "\n" \ 51 | "then execute it:\n" \ 52 | " " PHP_MICRO_HINT_CMDE "\n" 53 | 54 | #ifdef PHP_WIN32 55 | # define MICRO_SFX_EXPORT __declspec(dllexport) __declspec(noinline) 56 | #else 57 | # define MICRO_SFX_EXPORT __attribute__((visibility("default"))) 58 | #endif 59 | 60 | #define PHP_MICRO_INIMARK ((uint8_t[4]){0xfd, 0xf6, 0x69, 0xe6}) 61 | #define PHP_MICRO_INIENTRY(x) ("micro." #x) 62 | 63 | #ifdef _DEBUG 64 | extern int micro_debug; 65 | # define dbgprintf(...) \ 66 | do { \ 67 | if (micro_debug != 0) { \ 68 | printf(__VA_ARGS__); \ 69 | } \ 70 | } while (0) 71 | #else 72 | # define dbgprintf(...) 73 | #endif 74 | 75 | static inline const char *micro_slashize(const char *x) { 76 | size_t size = strlen(x); 77 | char *ret = malloc(size + 2); 78 | memcpy(ret, x, size); 79 | for (size_t i = 0; i < size; i++) { 80 | if ('\\' == ret[i]) { 81 | ret[i] = '/'; 82 | } 83 | } 84 | if ('/' != ret[size - 1]) { 85 | ret[size] = '/'; 86 | ret[size + 1] = '\0'; 87 | } else { 88 | ret[size] = '\0'; 89 | } 90 | // dbgprintf("slashed %s\n", ret); 91 | return ret; 92 | } 93 | 94 | #endif // _PHP_MICRO_H 95 | -------------------------------------------------------------------------------- /php_micro.rc: -------------------------------------------------------------------------------- 1 | #ifdef APSTUDIO_INVOKED 2 | # error Do not edit with MSVC 3 | #endif 4 | 5 | #include "winresrc.h" 6 | #include "main/php_version.h" 7 | #include "sapi/micro/php_micro.h" 8 | 9 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 10 | #pragma code_page(1252) 11 | 12 | #ifndef THANKS_GUYS 13 | # define THANKS_GUYS "" 14 | #endif 15 | 16 | #ifndef APP_LOGO 17 | #define APP_LOGO win32\build\php.ico 18 | #endif 19 | 20 | #ifdef WANT_LOGO 21 | 0 ICON APP_LOGO 22 | #endif 23 | 24 | #ifndef INTERNAL_NAME /* e.g. 'PHAR extension', 'CGI SAPI' */ 25 | # ifdef FILE_DESCRIPTION 26 | #define INTERNAL_NAME FILE_DESCRIPTION /* e.g. 'PHP Script Interpreter', 'GD imaging' */ 27 | # else 28 | #define INTERNAL_NAME FILE_NAME /* e.g. 'php7ts.dll', 'php_bz2.dll' */ 29 | # endif 30 | #endif 31 | 32 | #ifndef URL 33 | #define URL "http://www.php.net/" 34 | #endif 35 | 36 | #ifndef EXT_VERSION 37 | #define EXT_VERSION PHP_VERSION 38 | #endif 39 | 40 | #ifndef EXT_FILE_VERSION 41 | #define EXT_FILE_VERSION PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION 42 | #endif 43 | 44 | VS_VERSION_INFO VERSIONINFO 45 | FILEVERSION EXT_FILE_VERSION 46 | PRODUCTVERSION PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION 47 | FILEFLAGSMASK 0x3fL 48 | #ifdef _DEBUG 49 | FILEFLAGS (VS_FF_DEBUG|VS_FF_SPECIALBUILD) 50 | #else 51 | FILEFLAGS 0x0L 52 | #endif 53 | FILEOS VOS__WINDOWS32 54 | FILETYPE VFT_DLL 55 | FILESUBTYPE VFT2_UNKNOWN 56 | BEGIN 57 | BLOCK "StringFileInfo" 58 | BEGIN 59 | BLOCK "040904b0" 60 | BEGIN 61 | VALUE "Comments", THANKS_GUYS 62 | VALUE "CompanyName", "The PHP Group" 63 | #ifdef _DEBUG 64 | VALUE "FileDescription", FILE_DESCRIPTION " (DEBUG)" 65 | #else 66 | VALUE "FileDescription", FILE_DESCRIPTION 67 | #endif 68 | VALUE "FileVersion", EXT_VERSION 69 | VALUE "InternalName", INTERNAL_NAME 70 | VALUE "LegalCopyright", "Copyright (c) The PHP Group" 71 | VALUE "LegalTrademarks", "PHP" 72 | VALUE "OriginalFilename", FILE_NAME 73 | VALUE "ProductName", "PHP" 74 | VALUE "ProductVersion", PHP_VERSION 75 | #ifdef _DEBUG 76 | VALUE "SpecialBuild", "Debug build" 77 | #endif 78 | VALUE "URL", URL 79 | END 80 | END 81 | BLOCK "VarFileInfo" 82 | BEGIN 83 | VALUE "Translation", 0x409, 1200 84 | END 85 | END 86 | 87 | #ifdef MC_INCLUDE 88 | #include MC_INCLUDE 89 | #endif 90 | -------------------------------------------------------------------------------- /php_micro_fileinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro_filesize.h 3 | filesize reproduction utilities for micro 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | #ifndef _PHP_MICRO_FILESIZE_H 22 | #define _PHP_MICRO_FILESIZE_H 23 | 24 | #include 25 | 26 | #include "php.h" 27 | 28 | size_t micro_get_sfxsize(void); 29 | size_t micro_get_sfxsize_limit(void); 30 | 31 | #ifdef PHP_WIN32 32 | /* 33 | * micro_get_filename_w - get self filename abs path (widechar) 34 | */ 35 | const wchar_t *micro_get_filename_w(void); 36 | #endif 37 | /* 38 | * micro_get_filename - get self filename abs path (char *) 39 | */ 40 | const char *micro_get_filename(void); 41 | /* 42 | * micro_get_filename_len - get self filename abs path (char *) length 43 | */ 44 | size_t micro_get_filename_len(void); 45 | /* 46 | * micro_get_filename_slashed - get self filename with s/\\/\//g 47 | */ 48 | extern const char *(*micro_get_filename_slashed)(void); 49 | 50 | extern struct _ext_ini { 51 | size_t size; 52 | char *data; 53 | } micro_ext_ini; 54 | /* 55 | * micro_fileinfo_init - prepare micro_ext_ini for ext ini support 56 | */ 57 | int micro_fileinfo_init(void); 58 | 59 | // things for phar hook (deprecated) 60 | 61 | #ifdef MICRO_USE_OLD_PHAR_HOOK 62 | /* 63 | * is_stream_self - check if a phpstream is opened self 64 | */ 65 | int is_stream_self(php_stream *stream); 66 | /* 67 | * micro_php_stream_rewind - rewind a stream with offset 68 | */ 69 | # define micro_php_stream_rewind(stream) \ 70 | (is_stream_self(stream) ? _php_stream_seek(stream, micro_get_sfxsize(), SEEK_SET) \ 71 | : _php_stream_seek(stream, 0, SEEK_SET)) 72 | /* 73 | * micro_php_stream_seek - seek a stream with offset 74 | */ 75 | # define micro_php_stream_seek(stream, offset, whence) \ 76 | (is_stream_self(stream) && SEEK_SET == whence ? dbgprintf("seeking with offset\n"), \ 77 | _php_stream_seek(stream, offset + micro_get_sfxsize(), SEEK_SET) \ 78 | : _php_stream_seek(stream, 0, SEEK_SET)) 79 | #endif 80 | /* 81 | * zif_micro_get_sfx_filesize 82 | * micro_get_sfx_filesize() -> int 83 | * get sfx size in bytes 84 | * deprecated 85 | */ 86 | PHPAPI PHP_FUNCTION(micro_get_sfx_filesize); 87 | 88 | /* 89 | * zif_micro_get_sfxsize 90 | * micro_get_sfxsize() -> int 91 | * get sfx size in bytes 92 | */ 93 | PHPAPI PHP_FUNCTION(micro_get_sfxsize); 94 | 95 | /* 96 | * zif_micro_get_sfxsize_limit 97 | * micro_get_sfxsize_limit() -> int 98 | * get sfx size in bytes 99 | */ 100 | PHPAPI PHP_FUNCTION(micro_get_sfxsize_limit); 101 | 102 | /* 103 | * zif_micro_get_self_filename 104 | * micro_get_self_filename() -> string 105 | * get self absolute file path 106 | */ 107 | PHPAPI PHP_FUNCTION(micro_get_self_filename); 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /php_micro_helper.c: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro_helper.h 3 | micro helpers like dbgprintf 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | #include 21 | 22 | #include "php.h" 23 | 24 | #include "php_micro.h" 25 | #include "php_micro_fileinfo.h" 26 | 27 | #if defined(PHP_WIN32) && defined(_DEBUG) 28 | 29 | # include 30 | # include 31 | 32 | HANDLE hOut, hErr; 33 | 34 | int micro_helper_init(void) { 35 | hOut = GetStdHandle(STD_OUTPUT_HANDLE); 36 | if (INVALID_HANDLE_VALUE == hOut) { 37 | wprintf(L"failed get output handle\n"); 38 | return ENOMEM; 39 | } 40 | hErr = GetStdHandle(STD_ERROR_HANDLE); 41 | if (INVALID_HANDLE_VALUE == hErr) { 42 | wprintf(L"failed get err handle\n"); 43 | return ENOMEM; 44 | } 45 | return 0; 46 | } 47 | 48 | /* 49 | * micro_sprintf - a swprintf(3) like implemention for windows 50 | * only for debug in ffi calling procedure 51 | */ 52 | MICRO_SFX_EXPORT wchar_t *micro_sprintf(const wchar_t *fmt, ...) { 53 | LPVOID pBuf = NULL; 54 | va_list args; 55 | va_start(args, fmt); 56 | 57 | DWORD lenWords = 58 | FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, (LPWSTR)&pBuf, 0, &args); 59 | va_end(args); 60 | 61 | return pBuf; 62 | } 63 | 64 | /* 65 | * micro_wprintf - a wprintf(3) like implemention for windows 66 | * only for debug in ffi calling procedure 67 | */ 68 | MICRO_SFX_EXPORT int micro_wprintf(const wchar_t *fmt, ...) { 69 | LPVOID pBuf = NULL; 70 | va_list args; 71 | va_start(args, fmt); 72 | 73 | DWORD lenWords = 74 | FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, (LPWSTR)&pBuf, 0, &args); 75 | va_end(args); 76 | 77 | WriteConsoleW(hOut, pBuf, lenWords, &lenWords, 0); 78 | 79 | LocalFree(pBuf); 80 | return lenWords; 81 | } 82 | 83 | PHP_FUNCTION(micro_enum_modules) { 84 | HMODULE hMods[1024]; 85 | HANDLE hProcess = GetCurrentProcess(); 86 | DWORD cbNeeded = 0; 87 | 88 | if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) { 89 | for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { 90 | WCHAR szModName[MAX_PATH]; 91 | 92 | // Get the full path to the module's file. 93 | 94 | if (GetModuleFileNameExW(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(WCHAR))) { 95 | // Print the module name and handle value. 96 | 97 | printf("loaded: %S (%p)\n", szModName, hMods[i]); 98 | } 99 | } 100 | } 101 | RETURN_TRUE; 102 | } 103 | 104 | #endif // defined(PHP_WIN32) && defined(_DEBUG) 105 | 106 | #ifdef _DEBUG 107 | PHP_FUNCTION(micro_update_extension_dir) { 108 | char *new_dir; 109 | size_t new_dir_len; 110 | static int called = 0; 111 | 112 | ZEND_PARSE_PARAMETERS_START(1, 1) 113 | Z_PARAM_STRING(new_dir, new_dir_len) 114 | ZEND_PARSE_PARAMETERS_END(); 115 | 116 | dbgprintf("updating %s as extension_dir\n", new_dir); 117 | 118 | if (!called) { 119 | // first call here 120 | called = 1; 121 | } else { 122 | free(PG(extension_dir)); 123 | } 124 | PG(extension_dir) = strdup(new_dir); 125 | 126 | dbgprintf("now is %s\n", PG(extension_dir)); 127 | RETURN_TRUE; 128 | } 129 | 130 | // ffi debug functions here 131 | 132 | MICRO_SFX_EXPORT int testcall(int (*func)(int), int input) { 133 | printf("call %p with arg %d\n", func, input); 134 | int ret = func(input); 135 | printf("func(%d) = %d\n", input, ret); 136 | return ret; 137 | } 138 | 139 | MICRO_SFX_EXPORT void inspect(void *buf, int len) { 140 | uint8_t *pbuf = buf; 141 | for (uint32_t i = 0; i < len; i += 8) { 142 | printf("%04x:", i); 143 | for (uint8_t j = 0; i + j < len && j < 8; j++) { 144 | printf(" %02x", pbuf[i + j]); 145 | } 146 | printf(" "); 147 | for (uint8_t j = 0; i + j < len && j < 8; j++) { 148 | if (' ' <= pbuf[i + j] && pbuf[i + j] < 127) { 149 | printf("%c", pbuf[i + j]); 150 | } else { 151 | printf("."); 152 | } 153 | } 154 | printf("\n"); 155 | } 156 | } 157 | 158 | MICRO_SFX_EXPORT void emptyfunc(void) { 159 | } 160 | 161 | #endif //_DEBUG 162 | 163 | PHP_FUNCTION(micro_version) { 164 | array_init(return_value); 165 | zval zv; 166 | ZVAL_LONG(&zv, PHP_MICRO_VER_MAJ); 167 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &zv); 168 | ZVAL_LONG(&zv, PHP_MICRO_VER_MIN); 169 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &zv); 170 | ZVAL_LONG(&zv, PHP_MICRO_VER_PAT); 171 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &zv); 172 | #ifdef PHP_MICRO_VER_APP 173 | ZVAL_STRING(&zv, PHP_MICRO_VER_APP); 174 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &zv); 175 | #endif 176 | } 177 | 178 | PHP_FUNCTION(micro_open_self) { 179 | php_stream *stream = NULL; 180 | FILE *fp = VCWD_FOPEN(micro_get_filename(), "rb"); 181 | stream = php_stream_fopen_from_file(fp, "rb"); 182 | if (NULL == stream) { 183 | RETURN_FALSE; 184 | } 185 | php_stream_to_zval(stream, return_value); 186 | } 187 | 188 | #ifdef PHP_WIN32 189 | 190 | // for windows "win32" build to reallocate console 191 | PHP_FUNCTION(realloc_console) { 192 | BOOL ret = 0; 193 | zend_bool alloc = false; 194 | 195 | ZEND_PARSE_PARAMETERS_START(0, 1) 196 | Z_PARAM_OPTIONAL 197 | Z_PARAM_BOOL(alloc) 198 | ZEND_PARSE_PARAMETERS_END(); 199 | 200 | if (alloc) { 201 | ret = AllocConsole(); 202 | } else { 203 | ret = AttachConsole(ATTACH_PARENT_PROCESS); 204 | } 205 | 206 | if (ret) { 207 | _close(0); 208 | _close(1); 209 | _close(2); 210 | freopen("CONIN$", "r", stdin); 211 | freopen("CONOUT$", "w", __acrt_iob_func(1)); 212 | freopen("CONOUT$", "w", __acrt_iob_func(2)); 213 | } 214 | 215 | RETURN_BOOL(ret); 216 | } 217 | 218 | #endif // PHP_WIN32 -------------------------------------------------------------------------------- /php_micro_helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro_helper.h 3 | header for micro helpers 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | #ifndef _PHP_MICRO_DLHELPER_H 21 | #define _PHP_MICRO_DLHELPER_H 22 | 23 | #include "php.h" 24 | #include "php_micro.h" 25 | 26 | PHP_FUNCTION(micro_version); 27 | /* 28 | * micro_helper_init - prepare hErr and hOut for _myprintf 29 | */ 30 | int micro_helper_init(void); 31 | /* 32 | * micro_open_self_stream - prepare self stream without offset for php use 33 | */ 34 | // int micro_open_self_stream(void); 35 | 36 | /* 37 | * zif_micro_update_extension_dir 38 | * micro_update_extension_dir(newdir) -> bool 39 | * force add extension_dir out of ini 40 | * only for debug in windows 41 | */ 42 | PHP_FUNCTION(micro_update_extension_dir); 43 | /* 44 | * zif_micro_enum_modules 45 | * micro_enum_modules() -> bool 46 | * show current loaded modules(dll) 47 | * only for debug in windows 48 | */ 49 | PHP_FUNCTION(micro_enum_modules); 50 | /* 51 | * zif_micro_version 52 | * micro_version() -> array 53 | * get micro version 54 | * in array(): 55 | * [ , , , [append version]] 56 | * which , , is type of int, 57 | * if append version defined, append version will be string(value of PHP_MICRO_VER_APP), otherwise array length will 58 | * be 3 59 | */ 60 | PHP_FUNCTION(micro_version); 61 | /* 62 | * zif_micro_open_self 63 | * micro_open_self() -> mixed 64 | * return self php_stream handle as php resource, if it's already closed, return false 65 | */ 66 | PHP_FUNCTION(micro_open_self); 67 | 68 | #ifdef PHP_WIN32 69 | /* 70 | * zif_realloc_console 71 | * realloc_console() -> void 72 | * re-allocate console after console free'd, we can only do this in C because stdio is static varible in MT CRT 73 | */ 74 | PHP_FUNCTION(realloc_console); 75 | #endif // PHP_WIN32 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /php_micro_hooks.c: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro_hooks.c 3 | micro hooks for multi kinds of hooking 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | #include "php.h" 21 | 22 | #include "php_micro.h" 23 | #include "php_micro_fileinfo.h" 24 | 25 | /* ======== things for ini set ======== */ 26 | 27 | // original zend_post_startup_cb holder 28 | static int (*micro_zend_post_startup_cb_orig)(void) = NULL; 29 | /* 30 | * micro_post_mstartup - post mstartup callback called as zend_post_startup_cb 31 | * used to add ini_entries without additional_modules 32 | */ 33 | int micro_post_mstartup(void) { 34 | dbgprintf("start reg inientries\n"); 35 | const zend_ini_entry_def micro_ini_entries[] = { 36 | ZEND_INI_ENTRY(PHP_MICRO_INIENTRY(php_binary), "", ZEND_INI_PERDIR | ZEND_INI_SYSTEM, NULL){0}, 37 | }; 38 | int ret = zend_register_ini_entries(micro_ini_entries, 0); 39 | if (SUCCESS != ret) { 40 | return ret; 41 | } 42 | if (NULL != micro_zend_post_startup_cb_orig) { 43 | return micro_zend_post_startup_cb_orig(); 44 | } 45 | return ret; 46 | } 47 | /* 48 | * micro_register_post_startup_cb - register post mstartup callback 49 | */ 50 | int micro_register_post_startup_cb(void) { 51 | if (NULL != zend_post_startup_cb) { 52 | micro_zend_post_startup_cb_orig = (void *)zend_post_startup_cb; 53 | } 54 | zend_post_startup_cb = (void *)micro_post_mstartup; 55 | return SUCCESS; 56 | } 57 | 58 | /* ======== things for hooking php_stream ======== */ 59 | // my own ops struct 60 | typedef struct _micro_php_stream_ops { 61 | php_stream_ops ops; 62 | const php_stream_ops *ops_orig; 63 | } micro_php_stream_ops; 64 | 65 | // use original ops as ps->ops 66 | #define orig_ops(myops, ps) \ 67 | const php_stream_ops *myops = ps->ops; \ 68 | ps->ops = ((const micro_php_stream_ops *)(ps->ops))->ops_orig; 69 | // use with-offset ops as ps->ops 70 | #define ours_ops(ps) ps->ops = myops; 71 | #define ret_orig(rtyp, name, stream, args) \ 72 | do { \ 73 | orig_ops(myops, stream); \ 74 | rtyp ret = stream->ops->name(stream args); \ 75 | ours_ops(stream); \ 76 | return ret; \ 77 | } while (0) 78 | #define with_args(...) , __VA_ARGS__ 79 | #define nope 80 | 81 | /* ops proxies here 82 | * why there're many proxies: 83 | * php DO NOT have a explcit standard applied which 84 | * limits one php_stream op function (like ops->stat) MUST NOT call another one, 85 | * or limits one php_stream op function MUST NOT use its own modified php_stream_obs (like what i do). 86 | * so we use these proxies to call original operation functions 87 | */ 88 | /* stdio like functions - these are mandatory! */ 89 | static ssize_t micro_plain_files_write(php_stream *stream, const char *buf, size_t count) { 90 | ret_orig(ssize_t, write, stream, with_args(buf, count)); 91 | } 92 | static int micro_plain_files_flush(php_stream *stream) { 93 | ret_orig(int, flush, stream, nope); 94 | } 95 | /* these are optional */ 96 | static int micro_plain_files_cast(php_stream *stream, int castas, void **_ret) { 97 | ret_orig(int, cast, stream, with_args(castas, _ret)); 98 | } 99 | static int micro_plain_files_stat(php_stream *stream, php_stream_statbuf *ssb) { 100 | ret_orig(int, stat, stream, with_args(ssb)); 101 | } 102 | #undef ret_orig 103 | #undef with_args 104 | #undef nope 105 | /* end of ops proxies */ 106 | 107 | /* stream ops hookers */ 108 | /* 109 | * micro_plain_files_set_option - php_stream sef_option op with offset 110 | * to fix mmap-like behaiver 111 | */ 112 | static int micro_plain_files_set_option(php_stream *stream, int option, int value, void *ptrparam) { 113 | void *myptrparam = ptrparam; 114 | size_t limit; 115 | 116 | if (option == PHP_STREAM_OPTION_MMAP_API && value == PHP_STREAM_MMAP_MAP_RANGE) { 117 | dbgprintf("trying mmap self, let us mask it!\n"); 118 | php_stream_mmap_range *range = myptrparam; 119 | if (PHP_STREAM_MAP_MODE_READWRITE == range->mode || PHP_STREAM_MAP_MODE_SHARED_READWRITE == range->mode) { 120 | // self should not be writeable 121 | return PHP_STREAM_OPTION_RETURN_ERR; 122 | } 123 | range->offset = range->offset + micro_get_sfxsize(); 124 | /** 125 | * linux mmap(2) manpage said: 126 | * EOVERFLOW 127 | * The file is a regular file and 128 | * the value of off plus len exceeds the offset maximum established in the open file description 129 | * associated with fildes. 130 | * 131 | */ 132 | if ((limit = micro_get_sfxsize_limit()) != 0) { 133 | if (range->offset + range->length > limit) { 134 | #ifdef EOVERFLOW // is this necessary? 135 | errno = EOVERFLOW; 136 | #else 137 | errno = EINVAL; 138 | #endif // EOVERFLOW 139 | return PHP_STREAM_OPTION_RETURN_ERR; 140 | } 141 | } 142 | } 143 | orig_ops(myops, stream); 144 | int ret = stream->ops->set_option(stream, option, value, myptrparam); 145 | ours_ops(stream); 146 | return ret; 147 | } 148 | /* 149 | * micro_plain_files_seek_with_offset - php_stream seek op with offset 150 | * return -1 for failed or 0 for success (behaives like fseek) 151 | */ 152 | static int micro_plain_files_seek_with_offset( 153 | php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset) { 154 | dbgprintf("seeking %zd with sfxsize %zd limit %zd whence %d\n", 155 | offset, 156 | micro_get_sfxsize(), 157 | micro_get_sfxsize_limit(), 158 | whence); 159 | int ret = -1; 160 | zend_off_t want_offset, real_offset; 161 | zend_off_t sfxsize, limit; 162 | 163 | sfxsize = micro_get_sfxsize(); 164 | limit = micro_get_sfxsize_limit(); 165 | 166 | orig_ops(myops, stream); 167 | switch (whence) { 168 | case SEEK_SET: 169 | want_offset = offset + sfxsize; 170 | break; 171 | case SEEK_CUR: 172 | ret = stream->ops->seek(stream, 0, SEEK_CUR, &want_offset); 173 | if (-1 == ret) { 174 | goto error; 175 | } 176 | want_offset += offset; 177 | break; 178 | case SEEK_END: 179 | if (0 == limit) { 180 | ret = stream->ops->seek(stream, 0, SEEK_END, &limit); 181 | if (-1 == ret) { 182 | goto error; 183 | } 184 | } 185 | want_offset = limit + offset; 186 | break; 187 | } 188 | dbgprintf("want offset: %zd\n", want_offset); 189 | 190 | if (want_offset < sfxsize) { 191 | // seek before start 192 | goto error; 193 | } 194 | 195 | ret = stream->ops->seek(stream, want_offset, SEEK_SET, &real_offset); 196 | if (-1 == ret) { 197 | php_error_docref(NULL, E_WARNING, "Seek on self stream failed"); 198 | goto error; 199 | } 200 | 201 | ours_ops(stream); 202 | 203 | *newoffset = real_offset - sfxsize; 204 | 205 | dbgprintf("new offset: %zd\n", *newoffset); 206 | return 0; 207 | error: 208 | ours_ops(stream); 209 | // php_error_docref(NULL, E_WARNING, "Seek on self stream failed"); 210 | return -1; 211 | } 212 | 213 | /* 214 | * micro_plain_files_stat_with_offset - php_stream stat op with offset 215 | */ 216 | static int micro_plain_files_stat_with_offset(php_stream *stream, php_stream_statbuf *ssb) { 217 | int ret = -1; 218 | size_t limit = 0; 219 | 220 | orig_ops(myops, stream); 221 | ret = stream->ops->stat(stream, ssb); 222 | ours_ops(stream); 223 | if (-1 == ret) { 224 | return -1; 225 | } 226 | 227 | dbgprintf("stating real size %zd\n", ssb->sb.st_size); 228 | if ((limit = micro_get_sfxsize_limit()) > 0) { 229 | ssb->sb.st_size = limit - micro_get_sfxsize(); 230 | } else { 231 | ssb->sb.st_size -= micro_get_sfxsize(); 232 | } 233 | dbgprintf("stating with offset %zd\n", ssb->sb.st_size); 234 | return ret; 235 | } 236 | 237 | /* 238 | * micro_plain_files_read_with_offset - php_stream read op with offset 239 | */ 240 | static ssize_t micro_plain_files_read_with_offset(php_stream *stream, char *buf, size_t count) { 241 | ssize_t ret = 0; 242 | zend_off_t current; 243 | size_t limit; 244 | 245 | orig_ops(myops, stream); 246 | ret = stream->ops->seek(stream, 0, SEEK_CUR, ¤t); 247 | if (-1 == ret || current < 0) { 248 | ret = -1; 249 | goto error; 250 | } 251 | 252 | dbgprintf("limit %zd, current %zd, count %zd\n", micro_get_sfxsize_limit(), current, count); 253 | if ((limit = micro_get_sfxsize_limit()) > 0) { 254 | if (current >= limit) { 255 | // already at end 256 | goto error; 257 | } else if (((size_t)current) + count > limit) { 258 | count = limit - current; 259 | } 260 | } 261 | ret = stream->ops->read(stream, buf, count); 262 | error: 263 | ours_ops(stream); 264 | return ret; 265 | } 266 | 267 | /* 268 | * micro_plain_files_close_with_offset - php_stream close destroyer 269 | */ 270 | static int micro_plain_files_close_with_offset(php_stream *stream, int close_handle) { 271 | dbgprintf("closing with-offset file %p\n", stream); 272 | 273 | orig_ops(myops, stream); 274 | pefree((void *)myops, stream->is_persistent); 275 | // free(myops); 276 | int ret = stream->ops->close(stream, close_handle); 277 | return ret; 278 | } 279 | 280 | #undef orig_ops 281 | #undef ours_ops 282 | /* end of stream ops hookers */ 283 | 284 | /* 285 | * micro_modify_ops_with_offset - modify a with-offset ops struct, the argument ps must be created 286 | */ 287 | static inline int micro_modify_ops_with_offset(php_stream *ps, int mod_stat) { 288 | dbgprintf("compare %p, %p\n", ps->ops->close, micro_plain_files_close_with_offset); 289 | if (ps->ops->close == micro_plain_files_close_with_offset) { 290 | dbgprintf("offset alread set, skip it\n"); 291 | return FAILURE; 292 | } 293 | micro_php_stream_ops *ret = pemalloc(sizeof(*ret), ps->is_persistent); 294 | // micro_php_stream_ops *ret = malloc(sizeof(*ret)); 295 | (*ret).ops = (php_stream_ops){ 296 | // set with-offset op handlers 297 | .close = micro_plain_files_close_with_offset, 298 | .seek = NULL == ps->ops->seek ? NULL : micro_plain_files_seek_with_offset, 299 | .stat = NULL == ps->ops->stat ? NULL 300 | : (0 == mod_stat ? micro_plain_files_stat : micro_plain_files_stat_with_offset), 301 | // set proxies 302 | .write = micro_plain_files_write, 303 | .read = micro_plain_files_read_with_offset, 304 | .flush = micro_plain_files_flush, 305 | .cast = NULL == ps->ops->cast ? NULL : micro_plain_files_cast, 306 | .set_option = NULL == ps->ops->set_option ? NULL : micro_plain_files_set_option, 307 | // set original label 308 | .label = ps->ops->label, 309 | }; 310 | ret->ops_orig = ps->ops; 311 | dbgprintf("assigning psop %p\n", ret); 312 | ps->ops = (const php_stream_ops *)ret; 313 | return SUCCESS; 314 | } 315 | 316 | // holder for original php_plain_files_wrapper_ops 317 | const php_stream_wrapper_ops *micro_plain_files_wops_orig = NULL; 318 | static inline int initial_seek(php_stream *ps); 319 | /* 320 | * micro_plain_files_opener - stream_opener that modify ops according to filename 321 | * replaces php_plain_files_stream_opener 322 | * should be called after micro_fileinfo_init 323 | */ 324 | static php_stream *micro_plain_files_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, 325 | int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) { 326 | dbgprintf("opening file %s like plain file\n", filename); 327 | if (NULL == micro_plain_files_wops_orig) { 328 | // this should never happen 329 | return NULL; 330 | } 331 | static const char *self_filename_slashed = NULL; 332 | if (NULL == self_filename_slashed) { 333 | self_filename_slashed = micro_slashize(micro_get_filename()); 334 | } 335 | php_stream *ps = micro_plain_files_wops_orig->stream_opener( 336 | wrapper, filename, mode, options, opened_path, context STREAMS_REL_CC); 337 | if (NULL == ps) { 338 | return ps; 339 | } 340 | const char *filename_slashed = micro_slashize(filename); 341 | if (0 == strcmp(filename_slashed, self_filename_slashed)) { 342 | dbgprintf("opening self via php_stream, hook it\n"); 343 | if (SUCCESS == micro_modify_ops_with_offset(ps, 1)) { 344 | initial_seek(ps); 345 | } 346 | } 347 | free((void *)filename_slashed); 348 | dbgprintf("done opening plain file %p\n", ps); 349 | return ps; 350 | } 351 | 352 | /* 353 | * micro_plain_files_url_stater - url_stater that modify stat according to filename 354 | * replaces php_plain_files_url_stater 355 | * should be called after micro_fileinfo_init 356 | */ 357 | static int micro_plain_files_url_stater( 358 | php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context) { 359 | dbgprintf("stating file %s like plain file\n", url); 360 | if (NULL == micro_plain_files_wops_orig) { 361 | // this should never happen 362 | return FAILURE; 363 | } 364 | static const char *self_filename_slashed = NULL; 365 | if (NULL == self_filename_slashed) { 366 | self_filename_slashed = micro_slashize(micro_get_filename()); 367 | } 368 | int ret = micro_plain_files_wops_orig->url_stat(wrapper, url, flags, ssb, context); 369 | if (SUCCESS != ret) { 370 | return ret; 371 | } 372 | const char *filename_slashed = micro_slashize(url); 373 | if (0 == strcmp(filename_slashed, self_filename_slashed)) { 374 | dbgprintf("stating self via plain file wops, hook it\n"); 375 | ssb->sb.st_size -= micro_get_sfxsize(); 376 | } 377 | free((void *)filename_slashed); 378 | return ret; 379 | } 380 | 381 | // with-offset wrapper ops to replace php_plain_files_wrapper.wops 382 | static php_stream_wrapper_ops micro_plain_files_wops_with_offset; 383 | 384 | /* 385 | * micro_hook_plain_files_wops - hook plain file wrapper php_plain_files_wrapper 386 | */ 387 | int micro_hook_plain_files_wops(void) { 388 | micro_plain_files_wops_orig = php_plain_files_wrapper.wops; 389 | memcpy(µ_plain_files_wops_with_offset, micro_plain_files_wops_orig, sizeof(*micro_plain_files_wops_orig)); 390 | micro_plain_files_wops_with_offset.stream_opener = micro_plain_files_opener; 391 | micro_plain_files_wops_with_offset.url_stat = micro_plain_files_url_stater; 392 | // micro_plain_files_wops_with_offset.stream_opener = micro_php_stream_closer; 393 | php_plain_files_wrapper.wops = µ_plain_files_wops_with_offset; 394 | return SUCCESS; 395 | } 396 | 397 | /* ======== things for hooking url_stream ======== */ 398 | 399 | HashTable reregistered_protos = {0}; 400 | int reregistered_protos_inited = 0; 401 | 402 | typedef struct _micro_reregistered_proto { 403 | php_stream_wrapper *modified_wrapper; 404 | php_stream_wrapper_ops *modified_wops; 405 | php_stream_wrapper *orig_wrapper; 406 | char proto[1]; 407 | } micro_reregistered_proto; 408 | // no wrapper ops proxies here 409 | 410 | static inline int initial_seek(php_stream *ps); 411 | /* 412 | * micro_wrapper_stream_opener - modify ops according to filename 413 | * replaces someproto_wrapper_open_url 414 | * should be called after micro_fileinfo_init 415 | */ 416 | static php_stream *micro_wrapper_stream_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, 417 | int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) { 418 | dbgprintf("opening file %s like url\n", filename); 419 | 420 | micro_reregistered_proto *pproto = zend_hash_str_find_ptr(&reregistered_protos, (void *)wrapper, sizeof(*wrapper)); 421 | if (NULL == pproto) { 422 | // this should never happen 423 | return NULL; 424 | } 425 | static const char *self_filename_slashed = NULL; 426 | static size_t self_filename_slashed_len = 0; 427 | if (NULL == self_filename_slashed) { 428 | self_filename_slashed = micro_slashize(micro_get_filename()); 429 | self_filename_slashed_len = strlen(self_filename_slashed); 430 | } 431 | php_stream *ps = pproto->orig_wrapper->wops->stream_opener( 432 | wrapper, filename, mode, options, opened_path, context STREAMS_REL_CC); 433 | if (NULL == ps) { 434 | return ps; 435 | } 436 | const char *filename_slashed = micro_slashize(filename); 437 | if (strstr(filename, "://") && 438 | 0 == strncmp(strstr(filename_slashed, "://") + 3, self_filename_slashed, self_filename_slashed_len)) { 439 | dbgprintf("stream %s is in self\n", filename); 440 | if (SUCCESS == micro_modify_ops_with_offset(ps, 0)) { 441 | initial_seek(ps); 442 | } 443 | } 444 | free((void *)filename_slashed); 445 | dbgprintf("done opening file %p like url\n", ps); 446 | return ps; 447 | } 448 | 449 | #if PHP_VERSION_ID < 80100 450 | # define zend_string_init_existing_interned zend_string_init_interned 451 | #endif 452 | 453 | /* 454 | * micro_reregister_proto - hook some:// protocol 455 | * should be called after mstartup, before start execution 456 | */ 457 | int micro_reregister_proto(const char *proto) { 458 | dbgprintf("reregister proto %s\n", proto); 459 | 460 | php_stream_wrapper_ops *modified_wops = NULL; 461 | php_stream_wrapper *modified_wrapper = NULL; 462 | int ret = SUCCESS; 463 | HashTable *ht = php_stream_get_url_stream_wrappers_hash_global(); 464 | php_stream_wrapper *orig_wrapper = 465 | zend_hash_find_ptr(ht, zend_string_init_existing_interned(proto, strlen(proto), 1)); 466 | if (NULL == orig_wrapper) { 467 | // no wrapper found 468 | goto end; 469 | } 470 | 471 | if (SUCCESS != (ret = php_unregister_url_stream_wrapper(proto))) { 472 | dbgprintf("failed unregister proto %s\n", proto); 473 | goto end; 474 | } 475 | 476 | if (NULL == orig_wrapper->wops->stream_opener) { 477 | // no stream_opener, just say success 478 | dbgprintf("proto %s have no stream_opener\n", proto); 479 | goto end; 480 | } 481 | 482 | if (0 == reregistered_protos_inited) { 483 | zend_hash_init(&reregistered_protos, 0, NULL, ZVAL_PTR_DTOR, 1); 484 | reregistered_protos_inited = 1; 485 | } 486 | modified_wops = malloc(sizeof(*modified_wops)); 487 | modified_wrapper = malloc(sizeof(*modified_wrapper)); 488 | 489 | modified_wrapper->wops = modified_wops; 490 | modified_wrapper->abstract = orig_wrapper->abstract; 491 | modified_wrapper->is_url = orig_wrapper->is_url; 492 | 493 | // copy original to modified 494 | memcpy(modified_wops, orig_wrapper->wops, sizeof(*modified_wops)); 495 | 496 | // modify stream opener 497 | modified_wops->stream_opener = micro_wrapper_stream_opener; 498 | 499 | // re-register it 500 | if (SUCCESS != (ret = php_register_url_stream_wrapper(proto, modified_wrapper))) { 501 | dbgprintf("failed reregister proto %s\n", proto); 502 | goto end; 503 | }; 504 | 505 | // save info for freeing 506 | micro_reregistered_proto *pproto = malloc(sizeof(*pproto) + strlen(proto)); 507 | pproto->modified_wops = modified_wops; 508 | pproto->modified_wrapper = modified_wrapper; 509 | pproto->orig_wrapper = orig_wrapper; 510 | memcpy(pproto->proto, proto, strlen(proto) + 1); 511 | zend_hash_str_add_ptr(&reregistered_protos, (void *)modified_wrapper, sizeof(*modified_wrapper), pproto); 512 | dbgprintf("reregistered proto (label %s) %s %p => %p %p\n", 513 | orig_wrapper->wops->label, 514 | proto, 515 | orig_wrapper, 516 | modified_wrapper, 517 | modified_wops); 518 | 519 | return ret; 520 | end: 521 | if (modified_wops) { 522 | free(modified_wops); 523 | } 524 | if (modified_wrapper) { 525 | free(modified_wrapper); 526 | } 527 | return ret; 528 | } 529 | 530 | #ifdef ZEND_HASH_MAP_REVERSE_FOREACH_PTR 531 | # define HASH_REVERSE_FOREACH_PTR ZEND_HASH_MAP_REVERSE_FOREACH_PTR 532 | #else 533 | # define HASH_REVERSE_FOREACH_PTR ZEND_HASH_REVERSE_FOREACH_PTR 534 | #endif 535 | 536 | /* 537 | * micro_free_reregistered_protos - remove hook of protocol schemes 538 | * should be called before mshutdown, after rshutdown 539 | */ 540 | int micro_free_reregistered_protos(void) { 541 | int final_ret = SUCCESS; 542 | HASH_REVERSE_FOREACH_PTR(&reregistered_protos, micro_reregistered_proto * pproto) 543 | int ret = SUCCESS; 544 | const char *proto = pproto->proto; 545 | dbgprintf("free reregistered proto %s\n", proto); 546 | if (SUCCESS != (ret = php_unregister_url_stream_wrapper(proto))) { 547 | dbgprintf("failed unregister reregistered proto %s\n", proto); 548 | final_ret = ret; 549 | continue; 550 | } 551 | if (SUCCESS != (ret = php_register_url_stream_wrapper(proto, pproto->orig_wrapper))) { 552 | dbgprintf("failed restore reregistered proto %s\n", proto); 553 | final_ret = ret; 554 | continue; 555 | } 556 | free(pproto->modified_wrapper); 557 | free(pproto->modified_wops); 558 | free(pproto); 559 | ZEND_HASH_FOREACH_END_DEL(); 560 | return final_ret; 561 | } 562 | 563 | static inline int initial_seek(php_stream *ps) { 564 | dbgprintf("initial seeking\n"); 565 | zend_off_t dummy; 566 | if (0 == ps->position) { 567 | // not appending mode 568 | ps->ops->seek(ps, 0, SEEK_SET, &dummy); 569 | } else if (0 < ps->position) { 570 | // appending mode 571 | // this will only called after micro_fileinfo_init, 572 | // so it's sure thatself size wont be smaller then sfx size. 573 | ps->position -= micro_get_sfxsize(); 574 | ps->ops->seek(ps, ps->position, SEEK_SET, &dummy); 575 | } else { 576 | // self should be seekable, if not, why? 577 | abort(); 578 | } 579 | return SUCCESS; 580 | } 581 | 582 | /* ======== things for hooking zend_stream ======== */ 583 | 584 | static ssize_t micro_zend_stream_reader_with_offset(void *handle, char *buf, size_t len) { 585 | size_t limit = 0; 586 | FILE *fp = (FILE *)handle; 587 | zend_off_t cur = zend_fseek(fp, 0, SEEK_CUR); 588 | 589 | dbgprintf("reader %zd from %zd\n", len, cur); 590 | if ((limit = micro_get_sfxsize_limit()) > 0) { 591 | if (cur >= limit) { 592 | return 0; 593 | } else if (cur + len > limit) { 594 | len = limit - cur; 595 | } 596 | } 597 | dbgprintf("reader with offset len become %zd\n", len); 598 | return fread(buf, 1, len, fp); 599 | } 600 | 601 | static size_t micro_zend_stream_fsizer_with_offset(void *handle) { 602 | size_t limit = micro_get_sfxsize_limit(); 603 | 604 | if (limit > 0) { 605 | dbgprintf("fsizer return %zd\n", limit - micro_get_sfxsize()); 606 | return limit - micro_get_sfxsize(); 607 | } 608 | 609 | zend_stat_t buf = {0}; 610 | if (handle && zend_fstat(fileno((FILE *)handle), &buf) == 0) { 611 | #ifdef S_ISREG 612 | if (!S_ISREG(buf.st_mode)) { 613 | return 0; 614 | } 615 | #endif 616 | dbgprintf("fsizer return %zd\n", buf.st_size - micro_get_sfxsize()); 617 | return buf.st_size - micro_get_sfxsize(); 618 | } 619 | return -1; 620 | } 621 | 622 | static void micro_zend_stream_closer(void *handle) { 623 | fclose((FILE *)handle); 624 | } 625 | 626 | int micro_hook_file_handle(zend_file_handle *file_handle) { 627 | file_handle->type = ZEND_HANDLE_STREAM; 628 | file_handle->handle.stream.handle = file_handle->handle.fp; 629 | file_handle->handle.stream.isatty = 0; 630 | file_handle->handle.stream.reader = (zend_stream_reader_t)micro_zend_stream_reader_with_offset; 631 | file_handle->handle.stream.closer = (zend_stream_closer_t)micro_zend_stream_closer; 632 | file_handle->handle.stream.fsizer = (zend_stream_fsizer_t)micro_zend_stream_fsizer_with_offset; 633 | zend_fseek((FILE *)file_handle->handle.fp, micro_get_sfxsize(), SEEK_SET); 634 | return SUCCESS; 635 | } 636 | -------------------------------------------------------------------------------- /php_micro_hooks.h: -------------------------------------------------------------------------------- 1 | /* 2 | micro SAPI for PHP - php_micro_hooks.h 3 | micro hooks for multi kinds of hooking header 4 | 5 | Copyright 2020 Longyan 6 | Copyright 2022 Yun Dou 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | #ifndef _PHP_MICRO_HOOKS_H 21 | #define _PHP_MICRO_HOOKS_H 22 | 23 | #include "php_micro.h" 24 | 25 | /* 26 | * micro_register_post_startup_cb - register post mstartup callback 27 | */ 28 | int micro_register_post_startup_cb(void); 29 | /* 30 | * micro_hook_plain_files_wops - hook plain file wrapper php_plain_files_wrapper 31 | */ 32 | int micro_hook_plain_files_wops(void); 33 | /* 34 | * micro_reregister_proto - hook some:// protocol 35 | * should be called after mstartup, before start execution 36 | */ 37 | int micro_reregister_proto(const char *proto); 38 | /* 39 | * micro_free_reregistered_protos - remove hook of protocol schemes 40 | * should be called before mshutdown, after rshutdown 41 | */ 42 | int micro_free_reregistered_protos(void); 43 | /* 44 | * micro_hook_file_handle - hook file_handle with offset 45 | * only for self 46 | */ 47 | int micro_hook_file_handle(zend_file_handle *file_handle); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.exe 3 | 4 | */*.diff 5 | */*.out 6 | */*.php 7 | */*.exp 8 | */*.log 9 | */*.sh 10 | 11 | */*.phar 12 | 13 | -------------------------------------------------------------------------------- /tests/Readme.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | 这些测试或许可以通过修改的run-tests.php的命令行选项跳过 4 | 5 | these tests may be skipped in command line via modiffied run-tests.php 6 | 7 | - tests/basic/bug71273.phpt: TODO: write micro flavor test like this 8 | - tests/basic/consistent_float_string_casts.phpt: setlocale(3) may not be usable in static build 9 | - tests/lang/bug30638.phpt: setlocale(3) may not be usable in static build 10 | - Zend/tests/bug40236.phpt: fakephp has not -a support 11 | - Zend/tests/lc_ctype_inheritance.phpt: setlocale(3) may not be usable in static build 12 | - ext/phar/tests/cache_list/copyonwrite*.phar.php micro donot support write on self file 13 | - ext/pcntl/tests/pcntl_exec.phpt: fakephp not supported stdin codes yet 14 | - ext/standard/tests/general_functions/phpinfo.phpt: micro's phpinfo() is no same as cli 15 | - ext/standard/tests/url/get_headers_error_003.phpt: micro should not use cli "-S" command line option 16 | - ext/standard/tests/versioning/php_sapi_name.phpt: micro do not have a SAPI name "c$ci" 17 | 18 | these tests may failed if not using cli_checks.patch because of php internel sapi name checks. 19 | 20 | - tests/lang/bug45392.phpt 21 | -------------------------------------------------------------------------------- /tests/fakecmd.php: -------------------------------------------------------------------------------- 1 | 1) { 74 | if ( 75 | strlen($kv[1]) > 0 && // *val != '\0' 76 | false === strpos("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890", $kv[1][0]) // !isalnum(*val) && *val != '"' && *val != '\'' 77 | ) { 78 | $inisets .= $kv[0] . '="' . $kv[1] . "\"\n"; 79 | } else { 80 | $inisets .= $kv[0] . '=' . $kv[1] . "\n"; 81 | } 82 | } else { 83 | $inisets .= $def . "=1\n"; 84 | } 85 | goto gonext; 86 | case "-e": 87 | fprintf($errf, "not support for stdin codes yet\n"); 88 | exit(1); 89 | case "-f": 90 | if ($modeset) { 91 | fprintf($errf, "mode differ\n"); 92 | exit(1); 93 | } 94 | $modeset = true; 95 | $mainpath= argvalue2($arg); 96 | goto gonext; 97 | case "-?": 98 | case "-h": 99 | fprintf(STDOUT, "no help yet\n"); 100 | exit(0); 101 | case "-i": 102 | phpinfo(); 103 | exit(0); 104 | case "-l": 105 | fprintf($errf, "no lint yet\n"); 106 | exit(1); 107 | case "-m": 108 | $all = get_loaded_extensions(); 109 | $zmod = get_loaded_extensions(true); 110 | $pmod = array_diff($all, $zmod); 111 | echo "[PHP Modules]\n"; 112 | foreach ($pmod as $e) { 113 | echo "$e\n"; 114 | } 115 | echo "\n[Zend Modules]\n"; 116 | foreach ($zmod as $e) { 117 | echo "$e\n"; 118 | } 119 | echo "\n"; 120 | exit(0); 121 | case "-r": 122 | if ($modeset) { 123 | fprintf($errf, "mode differ\n"); 124 | exit(1); 125 | } 126 | $modeset = true; 127 | $maincode = argvalue2($arg); 128 | goto gonext; 129 | case "-B": 130 | case "-R": 131 | case "-F": 132 | case "-E": 133 | fprintf($errf, "-{B, R, F, E} not implement yet\n"); 134 | exit(1); 135 | case "-H": 136 | fprintf($errf, "-H not implement yet\n"); 137 | exit(1); 138 | case "-S": 139 | case "-t": 140 | fprintf($errf, "-{S, t} not implement yet\n"); 141 | exit(1); 142 | case "-s": 143 | fprintf($errf, "-s not implement yet\n"); 144 | exit(1); 145 | case "-v": 146 | echo "PHP " . PHP_VERSION . " (micro) (built: Jan 01 1970 00:00:00) ( NTS )\n" . 147 | "Copyright (c) The PHP Group\n" . 148 | "Zend Engine v0.0.0, Copyright (c) Zend Technologies\n" . 149 | (extension_loaded("Zend Opcache") ? "with Zend OPcache v" . PHP_VERSION . ", Copyright (c), by Zend Technologies" : "") . 150 | "\n"; 151 | exit(0); 152 | case "-w": 153 | fprintf($errf, "-w not implement yet\n"); 154 | exit(1); 155 | case "-z": 156 | $v = argvalue2($arg); 157 | $inisets .= "zend_extension=\"$v\"\n"; 158 | goto gonext; 159 | case "--": 160 | switch ($arg) { 161 | case "--ini": 162 | echo "Configuration File (php.ini) Path: (none)\n" . 163 | "Loaded Configuration File: (none)\n" . 164 | "Scan for additional .ini files in: (none)\n" . 165 | "Additional .ini files parsed: (none)\n"; 166 | exit(0); 167 | case "--rf": 168 | case "--rc": 169 | case "--re": 170 | case "--rz": 171 | case "--ri": 172 | fprintf($errf, "--r{f, c, e, z, i} not implement yet\n"); 173 | exit(1); 174 | case "--": 175 | $arg = array_shift($argv); 176 | // no break 177 | default: 178 | // continue 179 | } 180 | // no break 181 | default: 182 | // continue 183 | } 184 | 185 | if (!$modeset) { 186 | $modeset = true; 187 | $mainpath = $arg; 188 | } else { 189 | array_unshift($argv, $arg); 190 | } 191 | break; 192 | gonext: 193 | } 194 | 195 | if (!$modeset) { 196 | fprintf($errf, "run waht?\n"); 197 | exit(1); 198 | } 199 | 200 | set_error_handler(function (?int $errno = 0, ?string $errstr = "", ?string $errfile = "", ?int $errline = 0, ?array $errcontext = null) use ($orig_argv) { 201 | global $errf; 202 | $fullcmd = implode(" ", $orig_argv); 203 | fprintf($errf, "$errstr \n at $errfile:$errline\n while processing cmd:\n $fullcmd\n"); 204 | exit(1); 205 | }); 206 | 207 | const BUFSIZE = 4096; 208 | function writesfx($out) 209 | { 210 | $sfx = micro_open_self(); 211 | // write sfx header 212 | $size = micro_get_sfxsize(); 213 | for (; $size > 0; $size -= BUFSIZE) { 214 | fwrite($out, fread($sfx, $size > BUFSIZE ? BUFSIZE : $size)); 215 | } 216 | fclose($sfx); 217 | } 218 | 219 | function writeinis($out, $inisets) 220 | { 221 | if (strlen($inisets)>0) { 222 | fwrite($out, "\xfd\xf6\x69\xe6"); 223 | fwrite($out, pack("N", strlen($inisets))); 224 | fwrite($out, $inisets); 225 | } 226 | } 227 | 228 | function writecode($out, $path) 229 | { 230 | $in = fopen($path, "rb"); 231 | do { 232 | $wrote = fwrite($out, fread($in, BUFSIZE)); 233 | } while (BUFSIZE === $wrote); 234 | fclose($in); 235 | } 236 | 237 | $ret = null; 238 | if (isset($mainpath)) { 239 | if (!preg_match('|~{0,1}/.+|', $mainpath)) { 240 | if (PHP_OS_FAMILY !== 'Windows') { 241 | $mainpath = './' . $mainpath; 242 | } 243 | } 244 | $outpath = $mainpath . ".exe"; 245 | $out = fopen($outpath, "wb"); 246 | 247 | writesfx($out); 248 | writeinis($out, $inisets); 249 | writecode($out, $mainpath); 250 | fclose($out); 251 | chmod($outpath, 0755); 252 | 253 | // switch php and exe 254 | rename($mainpath, $mainpath . ".orig"); 255 | rename($outpath, $mainpath); 256 | //copy($mainpath, $outpath); 257 | passthru($mainpath . " " . implode(" ", $argv), $ret); 258 | rename($mainpath . ".orig", $mainpath); 259 | } else { 260 | $outpath = "temp.exe"; 261 | if (PHP_OS_FAMILY !== 'Windows') { 262 | $outpath = './' . $outpath; 263 | } 264 | $out = fopen($outpath, "wb"); 265 | 266 | writesfx($out); 267 | writeinis($out, $inisets); 268 | fwrite($out, "\x3c?php " .$maincode); 269 | fclose($out); 270 | chmod($outpath, 0755); 271 | 272 | //echo ($outpath . " " . implode(" ", $argv) . PHP_EOL); 273 | passthru($outpath . " " . implode(" ", $argv), $ret); 274 | } 275 | 276 | 277 | // remove temp executable 278 | if (is_file($outpath)) { 279 | unlink($outpath); 280 | } 281 | exit($ret); 282 | -------------------------------------------------------------------------------- /tests/micro/argvs.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test $argv variable things 3 | --SKIPIF-- 4 | 17 | string(%d) "%sargvs.php" 18 | [1]=> 19 | string(7) "-param1" 20 | [2]=> 21 | string(3) "-p2" 22 | [3]=> 23 | string(3) "/p3" 24 | [4]=> 25 | string(3) "123" 26 | [5]=> 27 | string(3) "321" 28 | } 29 | int(6) 30 | array(6) { 31 | [0]=> 32 | string(%d) "%sargvs.php" 33 | [1]=> 34 | string(7) "-param1" 35 | [2]=> 36 | string(3) "-p2" 37 | [3]=> 38 | string(3) "/p3" 39 | [4]=> 40 | string(3) "123" 41 | [5]=> 42 | string(3) "321" 43 | } 44 | int(6) 45 | -------------------------------------------------------------------------------- /tests/micro/micro_open_self.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test micro_open_self() function 3 | --SKIPIF-- 4 | 12 | --INI-- 13 | phar.readonly=0 14 | --FILE-- 15 | startBuffering(); 77 | $phar->addFromString("index.php", $index); 78 | $phar->addFromString("lv1.php", $lv1); 79 | $phar->addFromString("lv2.php", $lv2); 80 | $phar->addFromString("lv3.php", $lv3); 81 | // NOTE: seek_self.inc have different behavior in phar 82 | // so the expect is different, this is not a bug. 83 | $phar->addFile("seek_self.inc", "seek_self.inc"); 84 | $phar->stopBuffering(); 85 | 86 | if ($phar->canCompress(Phar::GZ)) { 87 | $phar->compress(Phar::GZ); 88 | } 89 | $phar->setDefaultStub("index.php", "index.php"); 90 | 91 | $selffile = micro_open_self(); 92 | $exe = fopen("phartest.exe", "wb"); 93 | for ($i = 0; $i < micro_get_sfxsize(); $i += 8192) { 94 | $read = fread($selffile, micro_get_sfxsize() - $i > 8192 ? 8192 : micro_get_sfxsize() - $i); 95 | fwrite($exe, $read); 96 | } 97 | 98 | fwrite($exe, file_get_contents("testphar.phar")); 99 | fflush($exe); 100 | fclose($exe); 101 | fclose($selffile); 102 | 103 | chmod("phartest.exe", 0755); 104 | 105 | if (PHP_OS_FAMILY === 'Windows') { 106 | passthru('.\phartest.exe', $ret); 107 | } else { 108 | passthru("./phartest.exe", $ret); 109 | } 110 | if ($ret !== 0) { 111 | echo "Failed to execute phar\n"; 112 | exit(1); 113 | } 114 | 115 | echo "Done\n"; 116 | ?> 117 | --CLEAN-- 118 | 127 | --EXPECTF-- 128 | index.php 129 | include seek_self.inc from phar 130 | string(4) " 213 | string(9) "index.php" 214 | [1]=> 215 | string(7) "lv1.php" 216 | [2]=> 217 | string(7) "lv2.php" 218 | [3]=> 219 | string(7) "lv3.php" 220 | [4]=> 221 | string(13) "seek_self.inc" 222 | } 223 | Done 224 | -------------------------------------------------------------------------------- /tests/micro/php_binary.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test if PHP_BINARY is remade correctly 3 | --SKIPIF-- 4 | 18 | --EXPECT-- 19 | string(8) "cafebabe" 20 | string(8) "cafebabe" 21 | -------------------------------------------------------------------------------- /tests/micro/seek_self.inc: -------------------------------------------------------------------------------- 1 | 9 | --FILE-- 10 | 86 | --EXPECTF-- 87 | string(4) "