├── .github
└── workflows
│ ├── phpcs.yml
│ ├── phpunit.yml
│ └── static-analysis.yml
├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── example
├── DummyFs.php
├── array_fs.php
├── dummy_file.php
├── dummy_file_oo.php
└── log_unimplemented.php
├── phpcs.xml
├── phpunit.xml.dist
├── psalm.xml
├── renovate.json
├── src
├── FFI
│ └── TypedCDataDefaultImplementationTrait.php
├── Filesystem
│ ├── BeforeAll
│ │ └── BeforeAllFilesystem.php
│ ├── Delegation
│ │ └── DelegationFilesystemTrait.php
│ ├── Log
│ │ └── LogUnimplementedFilesystem.php
│ ├── Null
│ │ └── NullFilesystem.php
│ ├── Overlay
│ │ └── OverlayFilesystem.php
│ └── ReflectionFilesystem.php
├── FilesystemDefaultImplementationTrait.php
├── FilesystemFlagsImplementationTrait.php
├── FilesystemInterface.php
├── Fuse.php
├── FuseLogicException.php
├── FuseOperations.php
├── Headers
│ └── fuse.h
├── Libc
│ ├── Errno
│ │ └── Errno.php
│ ├── Fcntl
│ │ └── Flock.php
│ ├── Fuse
│ │ ├── FuseBuf.php
│ │ ├── FuseBufVec.php
│ │ ├── FuseConnInfo.php
│ │ ├── FuseDirFill.php
│ │ ├── FuseDirHandle.php
│ │ ├── FuseFileInfo.php
│ │ ├── FuseFillDir.php
│ │ ├── FuseIoctlArgPointer.php
│ │ ├── FuseIoctlDataPointer.php
│ │ ├── FusePollHandle.php
│ │ ├── FusePrivateData.php
│ │ └── FuseReadDirBuffer.php
│ ├── String
│ │ ├── CBytesBuffer.php
│ │ └── CStringBuffer.php
│ ├── Sys
│ │ ├── Stat
│ │ │ └── Stat.php
│ │ └── StatVfs
│ │ │ └── StatVfs.php
│ ├── Time
│ │ └── TimeSpec.php
│ └── Utime
│ │ └── UtimBuf.php
├── Mountable.php
├── MountableFilesystemTrait.php
└── Mounter.php
├── tests
├── FFI
│ └── TypedCDataWrapperTest.php
└── Filesystem
│ ├── Log
│ └── LogUnimplementedFilesystemTest.php
│ └── ReflectionFilesystemTest.php
└── tools
└── stubs
├── FFI
└── CData.php
└── Fuse
├── FuseCData.php
└── FuseFFI.php
/.github/workflows/phpcs.yml:
--------------------------------------------------------------------------------
1 | name: PHP Coding Style Checker
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | pull_request:
8 | branches:
9 | - '*'
10 |
11 | jobs:
12 |
13 | phpcs:
14 | name: phpcs check codestyles
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - name: Setup PHP Action
20 | uses: shivammathur/setup-php@v2
21 | with:
22 | php-version: 7.4
23 | extensions: dom, mbstring
24 | coverage: none
25 | tools: cs2pr
26 |
27 | - name: Get Composer Cache Directory
28 | id: composer-cache
29 | run: echo "::set-output name=dir::$(composer config cache-files-dir)"
30 |
31 | - name: Cache dependencies
32 | uses: actions/cache@v2
33 | with:
34 | path: ${{ steps.composer-cache.outputs.dir }}
35 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
36 | restore-keys: ${{ runner.os }}-composer-
37 |
38 | - name: Install Dependencies
39 | run: composer install --prefer-dist --no-progress --no-suggest
40 |
41 | - name: Run phpcs
42 | run: vendor/bin/phpcs --standard=./phpcs.xml --report=checkstyle -q ./src ./tests | cs2pr
43 |
--------------------------------------------------------------------------------
/.github/workflows/phpunit.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | pull_request:
8 | branches:
9 | - '*'
10 |
11 | jobs:
12 |
13 | phpunit-test:
14 | name: phpunit test
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - name: Setup PHP Action
20 | uses: shivammathur/setup-php@v2
21 | with:
22 | php-version: 7.4
23 | extensions: ffi, dom, mbstring
24 | coverage: pcov
25 |
26 | - name: Install libfuse
27 | run: sudo apt-get install libfuse-dev
28 |
29 | - name: Get Composer Cache Directory
30 | id: composer-cache
31 | run: echo "::set-output name=dir::$(composer config cache-files-dir)"
32 |
33 | - name: Cache dependencies
34 | uses: actions/cache@v2
35 | with:
36 | path: ${{ steps.composer-cache.outputs.dir }}
37 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
38 | restore-keys: ${{ runner.os }}-composer-
39 |
40 | - name: Validate composer.json and composer.lock
41 | run: composer validate
42 |
43 | - name: Install dependencies
44 | run: composer install --prefer-dist --no-progress --no-suggest
45 |
46 | - name: Setup problem matchers for PHP
47 | run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
48 |
49 | - name: Setup Problem Matchers for PHPUnit
50 | run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
51 |
52 | - name: Run test suite
53 | run: |
54 | mkdir -p build/logs
55 | ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
56 |
57 | - name: Send to coveralls
58 | env:
59 | COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60 | run: ./vendor/bin/php-coveralls -v
61 |
--------------------------------------------------------------------------------
/.github/workflows/static-analysis.yml:
--------------------------------------------------------------------------------
1 | name: PHP Static Analysis
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | pull_request:
8 | branches:
9 | - '*'
10 |
11 | jobs:
12 |
13 | psalm-analysis:
14 | name: psalm static code analysis
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - name: Setup PHP Action
20 | uses: shivammathur/setup-php@v2
21 | with:
22 | php-version: 7.4
23 | extensions: dom, mbstring
24 | coverage: none
25 |
26 | - name: Get Composer Cache Directory
27 | id: composer-cache
28 | run: echo "::set-output name=dir::$(composer config cache-files-dir)"
29 |
30 | - name: Cache dependencies
31 | uses: actions/cache@v2
32 | with:
33 | path: ${{ steps.composer-cache.outputs.dir }}
34 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
35 | restore-keys: ${{ runner.os }}-composer-
36 |
37 | - name: "Psalm cache"
38 | uses: actions/cache@v2
39 | with:
40 | path: /tmp/psalm
41 | key: "psalm-cache"
42 |
43 | - name: Install Dependencies
44 | run: composer install --prefer-dist --no-progress --no-suggest
45 |
46 | - name: Run psalm
47 | run: ./vendor/bin/psalm --shepherd --show-info=true --output-format=github
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) sji
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # php-fuse
2 |
3 | 
4 | [](https://packagist.org/packages/sj-i/php-fuse)
5 | [](https://github.com/sj-i/php-fuse/actions)
6 | [](https://scrutinizer-ci.com/g/sj-i/php-fuse/?branch=master)
7 | [](https://coveralls.io/github/sj-i/php-fuse?branch=master)
8 | 
9 | 
10 |
11 | PHP FFI bindings for [libfuse](https://github.com/libfuse/libfuse).
12 |
13 | You can write your own filesystems in PHP.
14 |
15 | ## Installation
16 | ```bash
17 | composer require sj-i/php-fuse
18 | ```
19 |
20 | ## Requirements
21 | - PHP 7.4+ (NTS / ZTS)
22 | - 64bit Linux x86_64
23 | - FFI extension
24 | - libfuse(currently based on 2.9.9)
25 |
26 | ## Documentation
27 | - Currently, no documentation is provided. :-(
28 | - If you want to write a filesystem in PHP by using this library, see [examples](https://github.com/sj-i/php-fuse/tree/master/example) in this repository and [the libfuse API documentation](https://libfuse.github.io/doxygen/index.html) for now.
29 |
30 | ## Todo
31 | - [ ] bump libfuse to 3.9
32 | - [ ] add more tests
33 | - [ ] add documentation
34 | - [ ] support multithreading
35 |
36 |
37 | ## LICENSE
38 | - MIT
39 |
40 | ## Example
41 | ```bash
42 | mkdir /tmp/example
43 | php example/dummy_file.php
44 | ```
45 |
46 | ```bash
47 | $ ls -la /tmp/example/
48 | total 180
49 | drwxr-xr-x 2 sji sji 0 1月 1 1970 .
50 | drwxrwxrwt 25 root root 180224 12月 28 07:14 ..
51 | -rwxrwxrwx 1 sji sji 20 1月 1 1970 example
52 | $ cat /tmp/example/example
53 | hello FUSE from PHP
54 | $ umount /tmp/example
55 | ```
56 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sj-i/php-fuse",
3 | "description": "PHP FFI bindings for FUSE",
4 | "type": "library",
5 | "minimum-stability": "dev",
6 | "license": "MIT",
7 | "keywords": [
8 | "php",
9 | "fuse",
10 | "ffi"
11 | ],
12 | "authors": [
13 | {
14 | "name": "sji",
15 | "homepage": "https://twitter.com/sji_ch"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "Fuse\\" : "src/"
21 | }
22 | },
23 | "require": {
24 | "php": "^7.4|^8.0",
25 | "ext-ffi": "*",
26 | "sj-i/phpdoc-type-reader": "0.1.1",
27 | "sj-i/typed-cdata": "0.0.5",
28 | "psr/log": "^1.1"
29 | },
30 | "require-dev": {
31 | "phpunit/phpunit": "9.5.9",
32 | "squizlabs/php_codesniffer": "3.6.0",
33 | "php-coveralls/php-coveralls": "2.4.3",
34 | "vimeo/psalm": "4.10.0",
35 | "jetbrains/phpstorm-stubs": "dev-master"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/example/DummyFs.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | use Fuse\FilesystemDefaultImplementationTrait;
15 | use Fuse\FilesystemInterface;
16 | use Fuse\Libc\Errno\Errno;
17 | use Fuse\Libc\Fuse\FuseFileInfo;
18 | use Fuse\Libc\Fuse\FuseFillDir;
19 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
20 | use Fuse\Libc\String\CBytesBuffer;
21 | use Fuse\Libc\Sys\Stat\Stat;
22 |
23 | class DummyFs implements FilesystemInterface
24 | {
25 | use FilesystemDefaultImplementationTrait;
26 |
27 | const FILE_PATH = '/example';
28 | const FILE_NAME = 'example';
29 | const FILE_CONTENT = 'hello FUSE from PHP' . PHP_EOL;
30 |
31 | public function getattr(string $path, Stat $stat): int
32 | {
33 | echo "attr read {$path}" . PHP_EOL;
34 |
35 | if ($path === '/') {
36 | $stat->st_mode = Stat::S_IFDIR | 0755;
37 | $stat->st_nlink = 2;
38 | $stat->st_uid = getmyuid();
39 | $stat->st_gid = getmygid();
40 | return 0;
41 | }
42 |
43 | if ($path === self::FILE_PATH) {
44 | $stat->st_mode = Stat::S_IFREG | 0777;
45 | $stat->st_nlink = 1;
46 | $stat->st_size = strlen(self::FILE_CONTENT);
47 | $stat->st_uid = getmyuid();
48 | $stat->st_gid = getmygid();
49 | return 0;
50 | }
51 |
52 | return -Errno::ENOENT;
53 | }
54 |
55 | public function readdir(
56 | string $path,
57 | FuseReadDirBuffer $buf,
58 | FuseFillDir $filler,
59 | int $offset,
60 | FuseFileInfo $fuse_file_info
61 | ): int {
62 | $filler($buf, '.', null, 0);
63 | $filler($buf, '..', null, 0);
64 | $filler($buf, self::FILE_NAME, null, 0);
65 |
66 | return 0;
67 | }
68 |
69 | public function open(string $path, FuseFileInfo $fuse_file_info): int
70 | {
71 | echo "open {$path}" . PHP_EOL;
72 |
73 | if ($path !== self::FILE_PATH) {
74 | return -Errno::ENOENT;
75 | }
76 |
77 | return 0;
78 | }
79 |
80 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
81 | {
82 | echo "read {$path}" . PHP_EOL;
83 |
84 | $len = strlen(self::FILE_CONTENT);
85 |
86 | if ($offset + $size > $len) {
87 | $size = ($len - $offset);
88 | }
89 |
90 | $content = substr(self::FILE_CONTENT, $offset, $size);
91 | $buffer->write($content, $size);
92 |
93 | return $size;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/example/array_fs.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | use Fuse\FilesystemDefaultImplementationTrait;
15 | use Fuse\FilesystemInterface;
16 | use Fuse\Libc\Errno\Errno;
17 | use Fuse\Libc\Fuse\FuseFileInfo;
18 | use Fuse\Libc\Fuse\FuseFillDir;
19 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
20 | use Fuse\Libc\String\CBytesBuffer;
21 | use Fuse\Libc\Sys\Stat\Stat;
22 | use Fuse\Mounter;
23 |
24 | require 'vendor/autoload.php';
25 |
26 | /**
27 | * @psalm-type NodeType=scalar|array|null
28 | */
29 | class ArrayFs implements FilesystemInterface
30 | {
31 | use FilesystemDefaultImplementationTrait;
32 |
33 | /** @var NodeType[] */
34 | private array $array;
35 |
36 | /**
37 | * ArrayFs constructor.
38 | * @param NodeType[] $array
39 | */
40 | public function __construct(array $array)
41 | {
42 | $this->array = $array;
43 | }
44 |
45 | public function getArray(): array
46 | {
47 | return $this->array;
48 | }
49 |
50 | public function getattr(string $path, Stat $stat): int
51 | {
52 | echo "attr read {$path}" . PHP_EOL;
53 |
54 | if ($path === '/') {
55 | $stat->st_mode = Stat::S_IFDIR | 0777;
56 | $stat->st_nlink = 2;
57 | $stat->st_uid = getmyuid();
58 | $stat->st_gid = getmygid();
59 | return 0;
60 | }
61 |
62 | $element = $this->getEntry($path);
63 | if (is_null($element)) {
64 | return -Errno::ENOENT;
65 | }
66 | if (is_array($element)) {
67 | $stat->st_mode = Stat::S_IFDIR | 0777;
68 | $stat->st_nlink = 2;
69 | $stat->st_uid = getmyuid();
70 | $stat->st_gid = getmygid();
71 | return 0;
72 | }
73 | $stat->st_mode = Stat::S_IFREG | 0777;
74 | $stat->st_nlink = 1;
75 | $stat->st_size = strlen((string)$element);
76 | $stat->st_uid = getmyuid();
77 | $stat->st_gid = getmygid();
78 | return 0;
79 | }
80 |
81 | /**
82 | * @param NodeType[] $array
83 | * @param list $offsets
84 | * @param callable(array, string):NodeType $operation
85 | * @return NodeType
86 | */
87 | private function &getRecursive(&$array, array $offsets, ?callable $operation = null)
88 | {
89 | $null = null;
90 |
91 | $count = count($offsets);
92 |
93 | if ($count === 0) {
94 | return $null;
95 | }
96 | if ($count === 1) {
97 | if (isset($array[$offsets[0]])) {
98 | if (!is_null($operation)) {
99 | return $operation($array, $offsets[0]);
100 | } else {
101 | /** @var NodeType */
102 | return $array[$offsets[0]];
103 | }
104 | } else {
105 | return $null;
106 | }
107 | }
108 |
109 | $offset = array_shift($offsets);
110 | if (is_array($array[$offset])) {
111 | /** @var NodeType[] $next_array */
112 | $next_array =& $array[$offset];
113 | return $this->getRecursive($next_array, $offsets);
114 | } else {
115 | return $null;
116 | }
117 | }
118 |
119 | /**
120 | * @param string $path
121 | * @return scalar|array|null
122 | */
123 | private function &getEntry(string $path)
124 | {
125 | if ($path === '/') {
126 | return $this->array;
127 | }
128 | $splitted = explode('/', $path);
129 | array_shift($splitted);
130 | return $this->getRecursive($this->array, $splitted);
131 | }
132 |
133 | /**
134 | * @param string $path
135 | * @return NodeType
136 | */
137 | private function &getParentEntry(string $path)
138 | {
139 | $splitted = explode('/', $path);
140 | array_shift($splitted);
141 | array_pop($splitted);
142 | if (count($splitted) === 0) {
143 | return $this->array;
144 | }
145 | return $this->getRecursive($this->array, $splitted);
146 | }
147 |
148 | /**
149 | * @param string $path
150 | */
151 | private function unsetEntry(string $path): void
152 | {
153 | $splitted = explode('/', $path);
154 | array_shift($splitted);
155 | $this->getRecursive(
156 | $this->array,
157 | $splitted,
158 | function &(array &$array, string $index) {
159 | $null = null;
160 | unset($array[$index]);
161 | return $null;
162 | }
163 | );
164 | }
165 |
166 | public function readdir(
167 | string $path,
168 | FuseReadDirBuffer $buf,
169 | FuseFillDir $filler,
170 | int $offset,
171 | FuseFileInfo $fuse_file_info
172 | ): int {
173 | $filler($buf, '.', null, 0);
174 | $filler($buf, '..', null, 0);
175 | $entry = $this->getEntry($path);
176 | if (!is_array($entry)) {
177 | return -Errno::ENOTDIR;
178 | }
179 | foreach ($entry as $key => $_) {
180 | $filler($buf, (string)$key, null, 0);
181 | }
182 |
183 | return 0;
184 | }
185 |
186 | public function open(string $path, FuseFileInfo $fuse_file_info): int
187 | {
188 | $entry = $this->getEntry($path);
189 | if (!is_scalar($entry)) {
190 | return Errno::ENOENT;
191 | }
192 |
193 | echo "open {$path}" . PHP_EOL;
194 | return 0;
195 | }
196 |
197 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
198 | {
199 | $entry = $this->getEntry($path);
200 |
201 | echo "read {$path}" . PHP_EOL;
202 |
203 | assert(!is_array($entry));
204 | $len = strlen((string)$entry);
205 |
206 | if ($offset + $size > $len) {
207 | $size = ($len - $offset);
208 | }
209 |
210 | $content = substr((string)$entry, $offset, $size);
211 | $buffer->write($content, $size);
212 |
213 | return $size;
214 | }
215 |
216 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
217 | {
218 | $entry = &$this->getEntry($path);
219 | assert(!is_array($entry));
220 | $entry = substr_replace((string)$entry, $buffer, $offset, $size);
221 |
222 | return $size;
223 | }
224 |
225 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int
226 | {
227 | $entry = &$this->getParentEntry($path);
228 | if (is_array($entry)) {
229 | $segments = explode('/', $path);
230 | $filename = array_pop($segments);
231 | $entry[$filename] = '';
232 | return 0;
233 | } else {
234 | return Errno::ENOENT;
235 | }
236 | }
237 |
238 | public function unlink(string $path): int
239 | {
240 | $this->unsetEntry($path);
241 | return 0;
242 | }
243 |
244 | public function rename(string $from, string $to): int
245 | {
246 | $fromValue = $this->getEntry($from);
247 | $parent_entry = &$this->getParentEntry($to);
248 | if (is_array($parent_entry)) {
249 | $segments = explode('/', $to);
250 | $filename = array_pop($segments);
251 | $parent_entry[$filename] = $fromValue;
252 | $this->unsetEntry($from);
253 | return 0;
254 | } else {
255 | return -Errno::ENOENT;
256 | }
257 | }
258 | }
259 |
260 | $e = new \DateTimeImmutable();
261 |
262 | $mounter = new Mounter();
263 | /** @psalm-suppress MixedArgumentTypeCoercion */
264 | $array_fs = new ArrayFs([
265 | 1,
266 | 2,
267 | 'foo' => 'bar',
268 | 'e' => json_decode(json_encode($e), true)
269 | ]);
270 | $result = $mounter->mount('/tmp/example/', $array_fs);
271 | /** @psalm-suppress ForbiddenCode */
272 | var_dump($array_fs->getArray());
273 | return $result;
--------------------------------------------------------------------------------
/example/dummy_file.php:
--------------------------------------------------------------------------------
1 | ffi->type(
20 | $typename
21 | );
22 | $size = FFI::sizeof(
23 | $type
24 | );
25 | echo "attr read {$path}" . PHP_EOL;
26 |
27 | FFI::memset($stbuf, 0, $size);
28 | if ($path === '/') {
29 | $stbuf->st_mode = Stat::S_IFDIR | 0755;
30 | $stbuf->st_nlink = 2;
31 | $stbuf->st_uid = getmyuid();
32 | $stbuf->st_gid = getmygid();
33 | return 0;
34 | }
35 |
36 | if ($path === FILE_PATH) {
37 | $stbuf->st_mode = Stat::S_IFREG | 0777;
38 | $stbuf->st_nlink = 1;
39 | $stbuf->st_size = strlen(FILE_CONTENT);
40 | $stbuf->st_uid = getmyuid();
41 | $stbuf->st_gid = getmygid();
42 | return 0;
43 | }
44 |
45 | return -Errno::ENOENT;
46 | }
47 |
48 | function readdir_cb(string $path, CData $buf, CData $filler, int $offset, CData $fi): int
49 | {
50 | $filler($buf, '.', null, 0);
51 | $filler($buf, '..', null, 0);
52 | $filler($buf, FILE_NAME, null, 0);
53 |
54 | return 0;
55 | }
56 |
57 | function open_cb(string $path, CData $fi): int
58 | {
59 | if ($path !== FILE_PATH) {
60 | return -Errno::ENOENT;
61 | }
62 |
63 | echo "open {$path}" . PHP_EOL;
64 | return 0;
65 | }
66 |
67 | function read_cb(string $path, CData $buf, int $size, int $offset, CData $fi): int
68 | {
69 | echo "read {$path}" . PHP_EOL;
70 |
71 | $len = strlen(FILE_CONTENT);
72 |
73 | if ($offset + $size > $len) {
74 | $size = ($len - $offset);
75 | }
76 |
77 | $content = substr(FILE_CONTENT, $offset, $size);
78 | FFI::memcpy($buf, $content, $size);
79 |
80 | return $size;
81 | }
82 |
83 | $fuse_operations = new FuseOperations();
84 | $fuse_operations->getattr = 'getattr_cb';
85 | $fuse_operations->open = 'open_cb';
86 | $fuse_operations->read = 'read_cb';
87 | $fuse_operations->readdir = 'readdir_cb';
88 |
89 | $mounter = new Mounter();
90 | return $mounter->mount('/tmp/example/', $fuse_operations);
91 |
--------------------------------------------------------------------------------
/example/dummy_file_oo.php:
--------------------------------------------------------------------------------
1 | mount('/tmp/example/', new DummyFs());
12 |
--------------------------------------------------------------------------------
/example/log_unimplemented.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | include __DIR__ . "/../vendor/autoload.php";
15 | include __DIR__ . "/DummyFs.php";
16 |
17 | use Fuse\Filesystem\Log\LogUnimplementedFilesystem;
18 | use Fuse\Mounter;
19 | use Psr\Log\LoggerInterface;
20 | use Psr\Log\LoggerTrait;
21 |
22 | $mounter = new Mounter();
23 |
24 | return $mounter->mount(
25 | '/tmp/example/',
26 | new LogUnimplementedFilesystem(
27 | new DummyFs(),
28 | new class() implements LoggerInterface {
29 | use LoggerTrait;
30 |
31 | public function log($level, $message, array $context = [])
32 | {
33 | echo \json_encode(['message' => $message] + $context), PHP_EOL;
34 | }
35 | }
36 | )
37 | );
38 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | php-fuse
4 |
5 |
6 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 | tests
20 |
21 |
22 |
23 |
24 |
25 | src
26 |
27 |
28 |
--------------------------------------------------------------------------------
/psalm.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/FFI/TypedCDataDefaultImplementationTrait.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\FFI;
15 |
16 | use FFI;
17 | use Fuse\Fuse;
18 | use TypedCData\TypedCDataDefaultImplementationTrait as BaseTrait;
19 |
20 | trait TypedCDataDefaultImplementationTrait
21 | {
22 | use BaseTrait;
23 |
24 | protected static function getFFI(): FFI
25 | {
26 | return Fuse::getInstance()->ffi;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Filesystem/BeforeAll/BeforeAllFilesystem.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\BeforeAll;
15 |
16 | use Fuse\FilesystemFlagsImplementationTrait;
17 | use Fuse\FilesystemInterface;
18 | use Fuse\Libc\Fcntl\Flock;
19 | use Fuse\Libc\Fuse\FuseBufVec;
20 | use Fuse\Libc\Fuse\FuseConnInfo;
21 | use Fuse\Libc\Fuse\FuseDirFill;
22 | use Fuse\Libc\Fuse\FuseDirHandle;
23 | use Fuse\Libc\Fuse\FuseFileInfo;
24 | use Fuse\Libc\Fuse\FuseFillDir;
25 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
26 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
27 | use Fuse\Libc\Fuse\FusePollHandle;
28 | use Fuse\Libc\Fuse\FusePrivateData;
29 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
30 | use Fuse\Libc\String\CBytesBuffer;
31 | use Fuse\Libc\String\CStringBuffer;
32 | use Fuse\Libc\Sys\Stat\Stat;
33 | use Fuse\Libc\Sys\StatVfs\StatVfs;
34 | use Fuse\Libc\Time\TimeSpec;
35 | use Fuse\Libc\Utime\UtimBuf;
36 | use Fuse\MountableFilesystemTrait;
37 | use TypedCData\TypedCDataArray;
38 |
39 | final class BeforeAllFilesystem implements FilesystemInterface
40 | {
41 | use MountableFilesystemTrait;
42 | use FilesystemFlagsImplementationTrait;
43 |
44 | /** @var callable */
45 | private $callback;
46 | private FilesystemInterface $filesystem;
47 |
48 | /**
49 | * @param callable(string,array):void $callback
50 | */
51 | public function __construct(
52 | callable $callback,
53 | FilesystemInterface $filesystem
54 | ) {
55 | $this->callback = $callback;
56 | $this->filesystem = $filesystem;
57 | }
58 |
59 | private function getFilesystem(): FilesystemInterface
60 | {
61 | return $this->filesystem;
62 | }
63 |
64 | public function getattr(string $path, Stat $stat): int
65 | {
66 | ($this->callback)(__FUNCTION__, func_get_args());
67 | return $this->getFilesystem()->getattr($path, $stat);
68 | }
69 |
70 | public function readlink(string $path, CStringBuffer $buffer, int $size): int
71 | {
72 | ($this->callback)(__FUNCTION__, func_get_args());
73 | return $this->getFilesystem()->readlink($path, $buffer, $size);
74 | }
75 |
76 | /** @deprecated */
77 | public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int
78 | {
79 | ($this->callback)(__FUNCTION__, func_get_args());
80 | /** @psalm-suppress DeprecatedMethod */
81 | return $this->getFilesystem()->getdir($path, $dirhandle, $dirfill);
82 | }
83 |
84 | public function mknod(string $path, int $mode, int $dev): int
85 | {
86 | ($this->callback)(__FUNCTION__, func_get_args());
87 | return $this->getFilesystem()->mknod($path, $mode, $dev);
88 | }
89 |
90 | public function mkdir(string $path, int $mode): int
91 | {
92 | ($this->callback)(__FUNCTION__, func_get_args());
93 | return $this->getFilesystem()->mkdir($path, $mode);
94 | }
95 |
96 | public function unlink(string $path): int
97 | {
98 | ($this->callback)(__FUNCTION__, func_get_args());
99 | return $this->getFilesystem()->unlink($path);
100 | }
101 |
102 | public function rmdir(string $path): int
103 | {
104 | ($this->callback)(__FUNCTION__, func_get_args());
105 | return $this->getFilesystem()->rmdir($path);
106 | }
107 |
108 | public function symlink(string $path, string $link): int
109 | {
110 | ($this->callback)(__FUNCTION__, func_get_args());
111 | return $this->getFilesystem()->symlink($path, $link);
112 | }
113 |
114 | public function rename(string $from, string $to): int
115 | {
116 | ($this->callback)(__FUNCTION__, func_get_args());
117 | return $this->getFilesystem()->rename($from, $to);
118 | }
119 |
120 | public function link(string $path, string $link): int
121 | {
122 | ($this->callback)(__FUNCTION__, func_get_args());
123 | return $this->getFilesystem()->link($path, $link);
124 | }
125 |
126 | public function chmod(string $path, int $mode): int
127 | {
128 | ($this->callback)(__FUNCTION__, func_get_args());
129 | return $this->getFilesystem()->chmod($path, $mode);
130 | }
131 |
132 | public function chown(string $path, int $uid, int $gid): int
133 | {
134 | ($this->callback)(__FUNCTION__, func_get_args());
135 | return $this->getFilesystem()->chown($path, $uid, $gid);
136 | }
137 |
138 | public function truncate(string $path, int $offset): int
139 | {
140 | ($this->callback)(__FUNCTION__, func_get_args());
141 | return $this->getFilesystem()->truncate($path, $offset);
142 | }
143 |
144 | public function utime(string $path, UtimBuf $utime_buf): int
145 | {
146 | ($this->callback)(__FUNCTION__, func_get_args());
147 | return $this->getFilesystem()->utime($path, $utime_buf);
148 | }
149 |
150 | public function open(string $path, FuseFileInfo $fuse_file_info): int
151 | {
152 | ($this->callback)(__FUNCTION__, func_get_args());
153 | return $this->getFilesystem()->open($path, $fuse_file_info);
154 | }
155 |
156 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
157 | {
158 | ($this->callback)(__FUNCTION__, func_get_args());
159 | return $this->getFilesystem()->read($path, $buffer, $size, $offset, $fuse_file_info);
160 | }
161 |
162 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
163 | {
164 | ($this->callback)(__FUNCTION__, func_get_args());
165 | return $this->getFilesystem()->write($path, $buffer, $size, $offset, $fuse_file_info);
166 | }
167 |
168 | public function statfs(string $path, StatVfs $statvfs): int
169 | {
170 | ($this->callback)(__FUNCTION__, func_get_args());
171 | return $this->getFilesystem()->statfs($path, $statvfs);
172 | }
173 |
174 | public function flush(string $path, FuseFileInfo $fuse_file_info): int
175 | {
176 | ($this->callback)(__FUNCTION__, func_get_args());
177 | return $this->getFilesystem()->flush($path, $fuse_file_info);
178 | }
179 |
180 | public function release(string $path, FuseFileInfo $fuse_file_info): int
181 | {
182 | ($this->callback)(__FUNCTION__, func_get_args());
183 | return $this->getFilesystem()->release($path, $fuse_file_info);
184 | }
185 |
186 | public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int
187 | {
188 | ($this->callback)(__FUNCTION__, func_get_args());
189 | return $this->getFilesystem()->fsync($path, $flags, $fuse_file_info);
190 | }
191 |
192 | public function setxattr(string $path, string $name, string $value, int $size): int
193 | {
194 | ($this->callback)(__FUNCTION__, func_get_args());
195 | return $this->getFilesystem()->setxattr($path, $name, $value, $size);
196 | }
197 |
198 | public function getxattr(string $path, string $name, ?string &$value, int $size): int
199 | {
200 | ($this->callback)(__FUNCTION__, func_get_args());
201 | return $this->getFilesystem()->getxattr($path, $name, $value, $size);
202 | }
203 |
204 | public function listxattr(string $path, ?string &$value, int $size): int
205 | {
206 | ($this->callback)(__FUNCTION__, func_get_args());
207 | return $this->getFilesystem()->listxattr($path, $value, $size);
208 | }
209 |
210 | public function removexattr(string $path, string $name): int
211 | {
212 | ($this->callback)(__FUNCTION__, func_get_args());
213 | return $this->getFilesystem()->removexattr($path, $name);
214 | }
215 |
216 | public function opendir(string $path, FuseFileInfo $fuse_file_info): int
217 | {
218 | ($this->callback)(__FUNCTION__, func_get_args());
219 | return $this->getFilesystem()->opendir($path, $fuse_file_info);
220 | }
221 |
222 | public function readdir(
223 | string $path,
224 | FuseReadDirBuffer $buf,
225 | FuseFillDir $filler,
226 | int $offset,
227 | FuseFileInfo $fuse_file_info
228 | ): int {
229 | ($this->callback)(__FUNCTION__, func_get_args());
230 | return $this->getFilesystem()->readdir($path, $buf, $filler, $offset, $fuse_file_info);
231 | }
232 |
233 | public function releasedir(string $path, FuseFileInfo $fuse_file_info): int
234 | {
235 | ($this->callback)(__FUNCTION__, func_get_args());
236 | return $this->getFilesystem()->releasedir($path, $fuse_file_info);
237 | }
238 |
239 | public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int
240 | {
241 | ($this->callback)(__FUNCTION__, func_get_args());
242 | return $this->getFilesystem()->fsyncdir($path, $fuse_file_info);
243 | }
244 |
245 | public function init(FuseConnInfo $conn): ?FusePrivateData
246 | {
247 | ($this->callback)(__FUNCTION__, func_get_args());
248 | return $this->getFilesystem()->init($conn);
249 | }
250 |
251 | public function destroy(?FusePrivateData $private_data): void
252 | {
253 | ($this->callback)(__FUNCTION__, func_get_args());
254 | $this->getFilesystem()->destroy($private_data);
255 | }
256 |
257 | public function access(string $path, int $mode): int
258 | {
259 | ($this->callback)(__FUNCTION__, func_get_args());
260 | return $this->getFilesystem()->access($path, $mode);
261 | }
262 |
263 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int
264 | {
265 | ($this->callback)(__FUNCTION__, func_get_args());
266 | return $this->getFilesystem()->create($path, $mode, $fuse_file_info);
267 | }
268 |
269 | public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int
270 | {
271 | ($this->callback)(__FUNCTION__, func_get_args());
272 | return $this->getFilesystem()->ftruncate($path, $offset, $fuse_file_info);
273 | }
274 |
275 | public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int
276 | {
277 | ($this->callback)(__FUNCTION__, func_get_args());
278 | return $this->getFilesystem()->fgetattr($path, $stat, $fuse_file_info);
279 | }
280 |
281 | public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int
282 | {
283 | ($this->callback)(__FUNCTION__, func_get_args());
284 | return $this->getFilesystem()->lock($path, $fuse_file_info, $cmd, $flock);
285 | }
286 |
287 | /**
288 | * @param TypedCDataArray $tv
289 | */
290 | public function utimens(string $path, TypedCDataArray $tv): int
291 | {
292 | ($this->callback)(__FUNCTION__, func_get_args());
293 | return $this->getFilesystem()->utimens($path, $tv);
294 | }
295 |
296 | public function bmap(string $path, int $blocksize, int &$idx): int
297 | {
298 | ($this->callback)(__FUNCTION__, func_get_args());
299 | return $this->getFilesystem()->bmap($path, $blocksize, $idx);
300 | }
301 |
302 | public function ioctl(
303 | string $path,
304 | int $cmd,
305 | FuseIoctlArgPointer $arg,
306 | FuseFileInfo $fuse_file_info,
307 | int $flags,
308 | FuseIoctlDataPointer $data
309 | ): int {
310 | ($this->callback)(__FUNCTION__, func_get_args());
311 | return $this->getFilesystem()->ioctl($path, $cmd, $arg, $fuse_file_info, $flags, $data);
312 | }
313 |
314 | public function poll(
315 | string $path,
316 | FuseFileInfo $fuse_file_info,
317 | FusePollHandle $fuse_pollhandle,
318 | int &$reventsp
319 | ): int {
320 | ($this->callback)(__FUNCTION__, func_get_args());
321 | return $this->getFilesystem()->poll($path, $fuse_file_info, $fuse_pollhandle, $reventsp);
322 | }
323 |
324 | public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int
325 | {
326 | ($this->callback)(__FUNCTION__, func_get_args());
327 | return $this->getFilesystem()->writeBuf($path, $buf, $offset, $fuse_file_info);
328 | }
329 |
330 | /**
331 | * @param TypedCDataArray $bufp
332 | */
333 | public function readBuf(
334 | string $path,
335 | TypedCDataArray $bufp,
336 | int $size,
337 | int $offset,
338 | FuseFileInfo $fuse_file_info
339 | ): int {
340 | ($this->callback)(__FUNCTION__, func_get_args());
341 | return $this->getFilesystem()->readBuf($path, $bufp, $size, $offset, $fuse_file_info);
342 | }
343 |
344 | public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int
345 | {
346 | ($this->callback)(__FUNCTION__, func_get_args());
347 | return $this->getFilesystem()->flock($path, $fuse_file_info, $op);
348 | }
349 |
350 | public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int
351 | {
352 | ($this->callback)(__FUNCTION__, func_get_args());
353 | return $this->getFilesystem()->fallocate($path, $mode, $offset, $fuse_file_info);
354 | }
355 | }
356 |
--------------------------------------------------------------------------------
/src/Filesystem/Delegation/DelegationFilesystemTrait.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\Delegation;
15 |
16 | use Fuse\FilesystemFlagsImplementationTrait;
17 | use Fuse\FilesystemInterface;
18 | use Fuse\Libc\Fcntl\Flock;
19 | use Fuse\Libc\Fuse\FuseBufVec;
20 | use Fuse\Libc\Fuse\FuseConnInfo;
21 | use Fuse\Libc\Fuse\FuseDirFill;
22 | use Fuse\Libc\Fuse\FuseDirHandle;
23 | use Fuse\Libc\Fuse\FuseFileInfo;
24 | use Fuse\Libc\Fuse\FuseFillDir;
25 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
26 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
27 | use Fuse\Libc\Fuse\FusePollHandle;
28 | use Fuse\Libc\Fuse\FusePrivateData;
29 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
30 | use Fuse\Libc\String\CBytesBuffer;
31 | use Fuse\Libc\String\CStringBuffer;
32 | use Fuse\Libc\Sys\Stat\Stat;
33 | use Fuse\Libc\Sys\StatVfs\StatVfs;
34 | use Fuse\Libc\Time\TimeSpec;
35 | use Fuse\Libc\Utime\UtimBuf;
36 | use Fuse\MountableFilesystemTrait;
37 | use TypedCData\TypedCDataArray;
38 |
39 | trait DelegationFilesystemTrait
40 | {
41 | use MountableFilesystemTrait;
42 | use FilesystemFlagsImplementationTrait;
43 |
44 | private FilesystemInterface $filesystem;
45 |
46 | private function setDelegation(FilesystemInterface $filesystem): void
47 | {
48 | $this->filesystem = $filesystem;
49 | }
50 |
51 | /** @return int|null|FusePrivateData|void */
52 | private function delegate(string $method_name, array $args)
53 | {
54 | /** @var int|null|FusePrivateData|void */
55 | return $this->filesystem->$method_name(...$args);
56 | }
57 |
58 | /**
59 | * int (*getattr) (const char *, struct stat *);
60 | */
61 | public function getattr(string $path, Stat $stat): int
62 | {
63 | /** @var int */
64 | return $this->delegate(__FUNCTION__, func_get_args());
65 | }
66 |
67 | /**
68 | * int (*readlink) (const char *, char *, size_t);
69 | */
70 | public function readlink(string $path, CStringBuffer $buffer, int $size): int
71 | {
72 | /** @var int */
73 | return $this->delegate(__FUNCTION__, func_get_args());
74 | }
75 |
76 | /**
77 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
78 | *
79 | * @deprecated
80 | */
81 | public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int
82 | {
83 | /** @var int */
84 | return $this->delegate(__FUNCTION__, func_get_args());
85 | }
86 |
87 | /**
88 | * int (*mknod) (const char *, mode_t, dev_t);
89 | */
90 | public function mknod(string $path, int $mode, int $dev): int
91 | {
92 | /** @var int */
93 | return $this->delegate(__FUNCTION__, func_get_args());
94 | }
95 |
96 | /**
97 | * int (*mkdir) (const char *, mode_t);
98 | */
99 | public function mkdir(string $path, int $mode): int
100 | {
101 | /** @var int */
102 | return $this->delegate(__FUNCTION__, func_get_args());
103 | }
104 |
105 | /**
106 | * int (*unlink) (const char *);
107 | */
108 | public function unlink(string $path): int
109 | {
110 | /** @var int */
111 | return $this->delegate(__FUNCTION__, func_get_args());
112 | }
113 |
114 | /**
115 | * int (*rmdir) (const char *);
116 | */
117 | public function rmdir(string $path): int
118 | {
119 | /** @var int */
120 | return $this->delegate(__FUNCTION__, func_get_args());
121 | }
122 |
123 | /**
124 | * int (*symlink) (const char *, const char *);
125 | */
126 | public function symlink(string $path, string $link): int
127 | {
128 | /** @var int */
129 | return $this->delegate(__FUNCTION__, func_get_args());
130 | }
131 |
132 | /**
133 | * int (*rename) (const char *, const char *);
134 | */
135 | public function rename(string $from, string $to): int
136 | {
137 | /** @var int */
138 | return $this->delegate(__FUNCTION__, func_get_args());
139 | }
140 |
141 | /**
142 | * int (*link) (const char *, const char *);
143 | */
144 | public function link(string $path, string $link): int
145 | {
146 | /** @var int */
147 | return $this->delegate(__FUNCTION__, func_get_args());
148 | }
149 |
150 | /**
151 | * int (*chmod) (const char *, mode_t);
152 | */
153 | public function chmod(string $path, int $mode): int
154 | {
155 | /** @var int */
156 | return $this->delegate(__FUNCTION__, func_get_args());
157 | }
158 |
159 | /**
160 | * int (*chown) (const char *, uid_t, gid_t);
161 | */
162 | public function chown(string $path, int $uid, int $gid): int
163 | {
164 | /** @var int */
165 | return $this->delegate(__FUNCTION__, func_get_args());
166 | }
167 |
168 | /**
169 | * int (*truncate) (const char *, off_t);
170 | */
171 | public function truncate(string $path, int $offset): int
172 | {
173 | /** @var int */
174 | return $this->delegate(__FUNCTION__, func_get_args());
175 | }
176 |
177 | /**
178 | * int (*utime) (const char *, struct utimbuf *);
179 | */
180 | public function utime(string $path, UtimBuf $utime_buf): int
181 | {
182 | /** @var int */
183 | return $this->delegate(__FUNCTION__, func_get_args());
184 | }
185 |
186 | /**
187 | * int (*open) (const char *, struct fuse_file_info *);
188 | */
189 | public function open(string $path, FuseFileInfo $fuse_file_info): int
190 | {
191 | /** @var int */
192 | return $this->delegate(__FUNCTION__, func_get_args());
193 | }
194 |
195 | /**
196 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
197 | */
198 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
199 | {
200 | /** @var int */
201 | return $this->delegate(__FUNCTION__, func_get_args());
202 | }
203 |
204 | /**
205 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
206 | */
207 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
208 | {
209 | /** @var int */
210 | return $this->delegate(__FUNCTION__, func_get_args());
211 | }
212 |
213 | /**
214 | * int (*statfs) (const char *, struct statvfs *);
215 | */
216 | public function statfs(string $path, StatVfs $statvfs): int
217 | {
218 | /** @var int */
219 | return $this->delegate(__FUNCTION__, func_get_args());
220 | }
221 |
222 | /**
223 | * int (*flush) (const char *, struct fuse_file_info *);
224 | */
225 | public function flush(string $path, FuseFileInfo $fuse_file_info): int
226 | {
227 | /** @var int */
228 | return $this->delegate(__FUNCTION__, func_get_args());
229 | }
230 |
231 | /**
232 | * int (*release) (const char *, struct fuse_file_info *);
233 | */
234 | public function release(string $path, FuseFileInfo $fuse_file_info): int
235 | {
236 | /** @var int */
237 | return $this->delegate(__FUNCTION__, func_get_args());
238 | }
239 |
240 | /**
241 | * int (*fsync) (const char *, int, struct fuse_file_info *);
242 | */
243 | public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int
244 | {
245 | /** @var int */
246 | return $this->delegate(__FUNCTION__, func_get_args());
247 | }
248 |
249 | /**
250 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
251 | */
252 | public function setxattr(string $path, string $name, string $value, int $size): int
253 | {
254 | /** @var int */
255 | return $this->delegate(__FUNCTION__, func_get_args());
256 | }
257 |
258 | /**
259 | * int (*getxattr) (const char *, const char *, char *, size_t);
260 | */
261 | public function getxattr(string $path, string $name, ?string &$value, int $size): int
262 | {
263 | /** @var int */
264 | return $this->delegate(__FUNCTION__, func_get_args());
265 | }
266 |
267 | /**
268 | * int (*listxattr) (const char *, char *, size_t);*
269 | */
270 | public function listxattr(string $path, ?string &$value, int $size): int
271 | {
272 | /** @var int */
273 | return $this->delegate(__FUNCTION__, func_get_args());
274 | }
275 |
276 | /**
277 | * int (*removexattr) (const char *, const char *);
278 | */
279 | public function removexattr(string $path, string $name): int
280 | {
281 | /** @var int */
282 | return $this->delegate(__FUNCTION__, func_get_args());
283 | }
284 |
285 | /**
286 | * int (*opendir) (const char *, struct fuse_file_info *);
287 | */
288 | public function opendir(string $path, FuseFileInfo $fuse_file_info): int
289 | {
290 | /** @var int */
291 | return $this->delegate(__FUNCTION__, func_get_args());
292 | }
293 |
294 | /**
295 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
296 | */
297 | public function readdir(
298 | string $path,
299 | FuseReadDirBuffer $buf,
300 | FuseFillDir $filler,
301 | int $offset,
302 | FuseFileInfo $fuse_file_info
303 | ): int {
304 | /** @var int */
305 | return $this->delegate(__FUNCTION__, func_get_args());
306 | }
307 |
308 | /**
309 | * int (*releasedir) (const char *, struct fuse_file_info *);
310 | */
311 | public function releasedir(string $path, FuseFileInfo $fuse_file_info): int
312 | {
313 | /** @var int */
314 | return $this->delegate(__FUNCTION__, func_get_args());
315 | }
316 |
317 | /**
318 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
319 | */
320 | public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int
321 | {
322 | /** @var int */
323 | return $this->delegate(__FUNCTION__, func_get_args());
324 | }
325 |
326 | /**
327 | * void *(*init) (struct fuse_conn_info *conn);
328 | */
329 | public function init(FuseConnInfo $conn): ?FusePrivateData
330 | {
331 | /** @var ?FusePrivateData */
332 | return $this->delegate(__FUNCTION__, func_get_args());
333 | }
334 |
335 | /**
336 | * void (*destroy) (void *);
337 | */
338 | public function destroy(?FusePrivateData $private_data): void
339 | {
340 | $this->delegate(__FUNCTION__, func_get_args());
341 | }
342 |
343 | /**
344 | * int (*access) (const char *, int);
345 | */
346 | public function access(string $path, int $mode): int
347 | {
348 | /** @var int */
349 | return $this->delegate(__FUNCTION__, func_get_args());
350 | }
351 |
352 | /**
353 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
354 | */
355 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int
356 | {
357 | /** @var int */
358 | return $this->delegate(__FUNCTION__, func_get_args());
359 | }
360 |
361 | /**
362 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
363 | */
364 | public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int
365 | {
366 | /** @var int */
367 | return $this->delegate(__FUNCTION__, func_get_args());
368 | }
369 |
370 | /**
371 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
372 | */
373 | public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int
374 | {
375 | /** @var int */
376 | return $this->delegate(__FUNCTION__, func_get_args());
377 | }
378 |
379 | /**
380 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
381 | */
382 | public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int
383 | {
384 | /** @var int */
385 | return $this->delegate(__FUNCTION__, func_get_args());
386 | }
387 |
388 | /**
389 | * int (*utimens) (const char *, const struct timespec tv[2]);
390 | *
391 | * @param TypedCDataArray $tv
392 | */
393 | public function utimens(string $path, TypedCDataArray $tv): int
394 | {
395 | /** @var int */
396 | return $this->delegate(__FUNCTION__, func_get_args());
397 | }
398 |
399 | /**
400 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
401 | */
402 | public function bmap(string $path, int $blocksize, int &$idx): int
403 | {
404 | /** @var int */
405 | return $this->delegate(__FUNCTION__, func_get_args());
406 | }
407 |
408 | /**
409 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
410 | */
411 | public function ioctl(
412 | string $path,
413 | int $cmd,
414 | FuseIoctlArgPointer $arg,
415 | FuseFileInfo $fuse_file_info,
416 | int $flags,
417 | FuseIoctlDataPointer $data
418 | ): int {
419 | /** @var int */
420 | return $this->delegate(__FUNCTION__, func_get_args());
421 | }
422 |
423 | /**
424 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
425 | */
426 | public function poll(
427 | string $path,
428 | FuseFileInfo $fuse_file_info,
429 | FusePollHandle $fuse_pollhandle,
430 | int &$reventsp
431 | ): int {
432 | /** @var int */
433 | return $this->delegate(__FUNCTION__, func_get_args());
434 | }
435 |
436 | /**
437 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
438 | */
439 | public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int
440 | {
441 | /** @var int */
442 | return $this->delegate(__FUNCTION__, func_get_args());
443 | }
444 |
445 | /**
446 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
447 | *
448 | * @param TypedCDataArray $bufp
449 | */
450 | public function readBuf(
451 | string $path,
452 | TypedCDataArray $bufp,
453 | int $size,
454 | int $offset,
455 | FuseFileInfo $fuse_file_info
456 | ): int {
457 | /** @var int */
458 | return $this->delegate(__FUNCTION__, func_get_args());
459 | }
460 |
461 | /**
462 | * int (*flock) (const char *, struct fuse_file_info *, int op);
463 | */
464 | public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int
465 | {
466 | /** @var int */
467 | return $this->delegate(__FUNCTION__, func_get_args());
468 | }
469 |
470 | /**
471 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
472 | */
473 | public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int
474 | {
475 | /** @var int */
476 | return $this->delegate(__FUNCTION__, func_get_args());
477 | }
478 | }
479 |
--------------------------------------------------------------------------------
/src/Filesystem/Log/LogUnimplementedFilesystem.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\Log;
15 |
16 | use Fuse\Filesystem\BeforeAll\BeforeAllFilesystem;
17 | use Fuse\Filesystem\Delegation\DelegationFilesystemTrait;
18 | use Fuse\Filesystem\Null\NullFilesystem;
19 | use Fuse\Filesystem\Overlay\OverlayFilesystem;
20 | use Fuse\FilesystemInterface;
21 | use Psr\Log\LoggerInterface;
22 | use Psr\Log\LogLevel;
23 |
24 | final class LogUnimplementedFilesystem implements FilesystemInterface
25 | {
26 | use DelegationFilesystemTrait;
27 |
28 | private const DEFAULT_MESSAGE = 'An unimplemented FUSE API is called';
29 |
30 | private const LOG_LEVELS = [
31 | LogLevel::EMERGENCY,
32 | LogLevel::ALERT,
33 | LogLevel::CRITICAL,
34 | LogLevel::ERROR,
35 | LogLevel::WARNING,
36 | LogLevel::NOTICE,
37 | LogLevel::INFO,
38 | LogLevel::DEBUG,
39 | ];
40 |
41 | private LoggerInterface $logger;
42 | private string $log_level;
43 | private string $message;
44 |
45 | /** @param value-of $log_level */
46 | public function __construct(
47 | FilesystemInterface $filesystem,
48 | LoggerInterface $logger,
49 | string $log_level = LogLevel::DEBUG,
50 | string $message = self::DEFAULT_MESSAGE
51 | ) {
52 | $this->initialize($filesystem);
53 | $this->logger = $logger;
54 | $this->log_level = $log_level;
55 | $this->message = $message;
56 | }
57 |
58 | private function initialize(FilesystemInterface $filesystem): void
59 | {
60 | $this->setDelegation(
61 | new OverlayFilesystem(
62 | $filesystem,
63 | new BeforeAllFilesystem(
64 | fn(string $method, array $args) => $this->log($method, $args),
65 | new NullFilesystem()
66 | )
67 | )
68 | );
69 | }
70 |
71 | private function log(string $method, array $args): void
72 | {
73 | $this->logger->log(
74 | $this->log_level,
75 | $this->message,
76 | [
77 | 'method' => $method,
78 | 'args' => $args
79 | ]
80 | );
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Filesystem/Null/NullFilesystem.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\Null;
15 |
16 | use Fuse\FilesystemDefaultImplementationTrait;
17 | use Fuse\FilesystemInterface;
18 |
19 | final class NullFilesystem implements FilesystemInterface
20 | {
21 | use FilesystemDefaultImplementationTrait;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Filesystem/Overlay/OverlayFilesystem.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\Overlay;
15 |
16 | use Fuse\Filesystem\ReflectionFilesystem;
17 | use Fuse\FilesystemFlagsImplementationTrait;
18 | use Fuse\FilesystemInterface;
19 | use Fuse\Libc\Fcntl\Flock;
20 | use Fuse\Libc\Fuse\FuseBufVec;
21 | use Fuse\Libc\Fuse\FuseConnInfo;
22 | use Fuse\Libc\Fuse\FuseDirFill;
23 | use Fuse\Libc\Fuse\FuseDirHandle;
24 | use Fuse\Libc\Fuse\FuseFileInfo;
25 | use Fuse\Libc\Fuse\FuseFillDir;
26 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
27 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
28 | use Fuse\Libc\Fuse\FusePollHandle;
29 | use Fuse\Libc\Fuse\FusePrivateData;
30 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
31 | use Fuse\Libc\String\CBytesBuffer;
32 | use Fuse\Libc\String\CStringBuffer;
33 | use Fuse\Libc\Sys\Stat\Stat;
34 | use Fuse\Libc\Sys\StatVfs\StatVfs;
35 | use Fuse\Libc\Time\TimeSpec;
36 | use Fuse\Libc\Utime\UtimBuf;
37 | use Fuse\MountableFilesystemTrait;
38 | use TypedCData\TypedCDataArray;
39 |
40 | final class OverlayFilesystem implements FilesystemInterface
41 | {
42 | use MountableFilesystemTrait;
43 | use FilesystemFlagsImplementationTrait;
44 |
45 | private FilesystemInterface $main;
46 | private FilesystemInterface $fallback;
47 |
48 | public function __construct(
49 | FilesystemInterface $main,
50 | FilesystemInterface $fallback
51 | ) {
52 | $this->main = $main;
53 | $this->fallback = $fallback;
54 | }
55 |
56 | /** @return int|FusePrivateData|null|void */
57 | private function fallbackIfDefault(string $method_name, array $args)
58 | {
59 | if (ReflectionFilesystem::instance($this->main)->isDefault($method_name)) {
60 | /** @var int|FusePrivateData|null|void */
61 | return $this->fallback->$method_name(...$args);
62 | }
63 | /** @var int|FusePrivateData|null|void */
64 | return $this->main->$method_name(...$args);
65 | }
66 |
67 | /**
68 | * int (*getattr) (const char *, struct stat *);
69 | */
70 | public function getattr(string $path, Stat $stat): int
71 | {
72 | /** @var int */
73 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
74 | }
75 |
76 | /**
77 | * int (*readlink) (const char *, char *, size_t);
78 | */
79 | public function readlink(string $path, CStringBuffer $buffer, int $size): int
80 | {
81 | /** @var int */
82 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
83 | }
84 |
85 | /**
86 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
87 | *
88 | * @deprecated
89 | */
90 | public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int
91 | {
92 | /** @var int */
93 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
94 | }
95 |
96 | /**
97 | * int (*mknod) (const char *, mode_t, dev_t);
98 | */
99 | public function mknod(string $path, int $mode, int $dev): int
100 | {
101 | /** @var int */
102 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
103 | }
104 |
105 | /**
106 | * int (*mkdir) (const char *, mode_t);
107 | */
108 | public function mkdir(string $path, int $mode): int
109 | {
110 | /** @var int */
111 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
112 | }
113 |
114 | /**
115 | * int (*unlink) (const char *);
116 | */
117 | public function unlink(string $path): int
118 | {
119 | /** @var int */
120 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
121 | }
122 |
123 | /**
124 | * int (*rmdir) (const char *);
125 | */
126 | public function rmdir(string $path): int
127 | {
128 | /** @var int */
129 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
130 | }
131 |
132 | /**
133 | * int (*symlink) (const char *, const char *);
134 | */
135 | public function symlink(string $path, string $link): int
136 | {
137 | /** @var int */
138 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
139 | }
140 |
141 | /**
142 | * int (*rename) (const char *, const char *);
143 | */
144 | public function rename(string $from, string $to): int
145 | {
146 | /** @var int */
147 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
148 | }
149 |
150 | /**
151 | * int (*link) (const char *, const char *);
152 | */
153 | public function link(string $path, string $link): int
154 | {
155 | /** @var int */
156 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
157 | }
158 |
159 | /**
160 | * int (*chmod) (const char *, mode_t);
161 | */
162 | public function chmod(string $path, int $mode): int
163 | {
164 | /** @var int */
165 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
166 | }
167 |
168 | /**
169 | * int (*chown) (const char *, uid_t, gid_t);
170 | */
171 | public function chown(string $path, int $uid, int $gid): int
172 | {
173 | /** @var int */
174 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
175 | }
176 |
177 | /**
178 | * int (*truncate) (const char *, off_t);
179 | */
180 | public function truncate(string $path, int $offset): int
181 | {
182 | /** @var int */
183 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
184 | }
185 |
186 | /**
187 | * int (*utime) (const char *, struct utimbuf *);
188 | */
189 | public function utime(string $path, UtimBuf $utime_buf): int
190 | {
191 | /** @var int */
192 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
193 | }
194 |
195 | /**
196 | * int (*open) (const char *, struct fuse_file_info *);
197 | */
198 | public function open(string $path, FuseFileInfo $fuse_file_info): int
199 | {
200 | /** @var int */
201 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
202 | }
203 |
204 | /**
205 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
206 | */
207 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
208 | {
209 | /** @var int */
210 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
211 | }
212 |
213 | /**
214 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
215 | */
216 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
217 | {
218 | /** @var int */
219 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
220 | }
221 |
222 | /**
223 | * int (*statfs) (const char *, struct statvfs *);
224 | */
225 | public function statfs(string $path, StatVfs $statvfs): int
226 | {
227 | /** @var int */
228 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
229 | }
230 |
231 | /**
232 | * int (*flush) (const char *, struct fuse_file_info *);
233 | */
234 | public function flush(string $path, FuseFileInfo $fuse_file_info): int
235 | {
236 | /** @var int */
237 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
238 | }
239 |
240 | /**
241 | * int (*release) (const char *, struct fuse_file_info *);
242 | */
243 | public function release(string $path, FuseFileInfo $fuse_file_info): int
244 | {
245 | /** @var int */
246 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
247 | }
248 |
249 | /**
250 | * int (*fsync) (const char *, int, struct fuse_file_info *);
251 | */
252 | public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int
253 | {
254 | /** @var int */
255 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
256 | }
257 |
258 | /**
259 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
260 | */
261 | public function setxattr(string $path, string $name, string $value, int $size): int
262 | {
263 | /** @var int */
264 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
265 | }
266 |
267 | /**
268 | * int (*getxattr) (const char *, const char *, char *, size_t);
269 | */
270 | public function getxattr(string $path, string $name, ?string &$value, int $size): int
271 | {
272 | /** @var int */
273 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
274 | }
275 |
276 | /**
277 | * int (*listxattr) (const char *, char *, size_t);*
278 | */
279 | public function listxattr(string $path, ?string &$value, int $size): int
280 | {
281 | /** @var int */
282 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
283 | }
284 |
285 | /**
286 | * int (*removexattr) (const char *, const char *);
287 | */
288 | public function removexattr(string $path, string $name): int
289 | {
290 | /** @var int */
291 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
292 | }
293 |
294 | /**
295 | * int (*opendir) (const char *, struct fuse_file_info *);
296 | */
297 | public function opendir(string $path, FuseFileInfo $fuse_file_info): int
298 | {
299 | /** @var int */
300 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
301 | }
302 |
303 | /**
304 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
305 | */
306 | public function readdir(
307 | string $path,
308 | FuseReadDirBuffer $buf,
309 | FuseFillDir $filler,
310 | int $offset,
311 | FuseFileInfo $fuse_file_info
312 | ): int {
313 | /** @var int */
314 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
315 | }
316 |
317 | /**
318 | * int (*releasedir) (const char *, struct fuse_file_info *);
319 | */
320 | public function releasedir(string $path, FuseFileInfo $fuse_file_info): int
321 | {
322 | /** @var int */
323 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
324 | }
325 |
326 | /**
327 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
328 | */
329 | public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int
330 | {
331 | /** @var int */
332 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
333 | }
334 |
335 | /**
336 | * void *(*init) (struct fuse_conn_info *conn);
337 | */
338 | public function init(FuseConnInfo $conn): ?FusePrivateData
339 | {
340 | /** @var null|FusePrivateData */
341 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
342 | }
343 |
344 | /**
345 | * void (*destroy) (void *);
346 | */
347 | public function destroy(?FusePrivateData $private_data): void
348 | {
349 | $this->fallbackIfDefault(__FUNCTION__, func_get_args());
350 | }
351 |
352 | /**
353 | * int (*access) (const char *, int);
354 | */
355 | public function access(string $path, int $mode): int
356 | {
357 | /** @var int */
358 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
359 | }
360 |
361 | /**
362 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
363 | */
364 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int
365 | {
366 | /** @var int */
367 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
368 | }
369 |
370 | /**
371 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
372 | */
373 | public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int
374 | {
375 | /** @var int */
376 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
377 | }
378 |
379 | /**
380 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
381 | */
382 | public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int
383 | {
384 | /** @var int */
385 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
386 | }
387 |
388 | /**
389 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
390 | */
391 | public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int
392 | {
393 | /** @var int */
394 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
395 | }
396 |
397 | /**
398 | * int (*utimens) (const char *, const struct timespec tv[2]);
399 | *
400 | * @param TypedCDataArray $tv
401 | */
402 | public function utimens(string $path, TypedCDataArray $tv): int
403 | {
404 | /** @var int */
405 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
406 | }
407 |
408 | /**
409 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
410 | */
411 | public function bmap(string $path, int $blocksize, int &$idx): int
412 | {
413 | /** @var int */
414 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
415 | }
416 |
417 | /**
418 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
419 | */
420 | public function ioctl(
421 | string $path,
422 | int $cmd,
423 | FuseIoctlArgPointer $arg,
424 | FuseFileInfo $fuse_file_info,
425 | int $flags,
426 | FuseIoctlDataPointer $data
427 | ): int {
428 | /** @var int */
429 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
430 | }
431 |
432 | /**
433 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
434 | */
435 | public function poll(
436 | string $path,
437 | FuseFileInfo $fuse_file_info,
438 | FusePollHandle $fuse_pollhandle,
439 | int &$reventsp
440 | ): int {
441 | /** @var int */
442 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
443 | }
444 |
445 | /**
446 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
447 | */
448 | public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int
449 | {
450 | /** @var int */
451 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
452 | }
453 |
454 | /**
455 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
456 | *
457 | * @param TypedCDataArray $bufp
458 | */
459 | public function readBuf(
460 | string $path,
461 | TypedCDataArray $bufp,
462 | int $size,
463 | int $offset,
464 | FuseFileInfo $fuse_file_info
465 | ): int {
466 | /** @var int */
467 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
468 | }
469 |
470 | /**
471 | * int (*flock) (const char *, struct fuse_file_info *, int op);
472 | */
473 | public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int
474 | {
475 | /** @var int */
476 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
477 | }
478 |
479 | /**
480 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
481 | */
482 | public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int
483 | {
484 | /** @var int */
485 | return $this->fallbackIfDefault(__FUNCTION__, func_get_args());
486 | }
487 | }
488 |
--------------------------------------------------------------------------------
/src/Filesystem/ReflectionFilesystem.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem;
15 |
16 | use Fuse\FilesystemDefaultImplementationTrait;
17 | use Fuse\FilesystemInterface;
18 | use ReflectionClass;
19 |
20 | final class ReflectionFilesystem
21 | {
22 | private FilesystemInterface $filesystem;
23 |
24 | public function __construct(FilesystemInterface $filesystem)
25 | {
26 | $this->filesystem = $filesystem;
27 | }
28 |
29 | public static function instance(FilesystemInterface $filesystem): self
30 | {
31 | return new self($filesystem);
32 | }
33 |
34 | public function isDefault(string $method_name): bool
35 | {
36 | $class = new ReflectionClass($this->filesystem);
37 | $method = $class->getMethod($method_name);
38 | $trait = new ReflectionClass(FilesystemDefaultImplementationTrait::class);
39 | return $method->getFileName() === $trait->getFileName();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/FilesystemDefaultImplementationTrait.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use Fuse\Libc\Errno\Errno;
17 | use Fuse\Libc\Fcntl\Flock;
18 | use Fuse\Libc\Fuse\FuseBufVec;
19 | use Fuse\Libc\Fuse\FuseConnInfo;
20 | use Fuse\Libc\Fuse\FuseDirFill;
21 | use Fuse\Libc\Fuse\FuseDirHandle;
22 | use Fuse\Libc\Fuse\FuseFileInfo;
23 | use Fuse\Libc\Fuse\FuseFillDir;
24 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
25 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
26 | use Fuse\Libc\Fuse\FusePollHandle;
27 | use Fuse\Libc\Fuse\FusePrivateData;
28 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
29 | use Fuse\Libc\String\CBytesBuffer;
30 | use Fuse\Libc\String\CStringBuffer;
31 | use Fuse\Libc\Sys\Stat\Stat;
32 | use Fuse\Libc\Sys\StatVfs\StatVfs;
33 | use Fuse\Libc\Time\TimeSpec;
34 | use Fuse\Libc\Utime\UtimBuf;
35 | use TypedCData\TypedCDataArray;
36 |
37 | trait FilesystemDefaultImplementationTrait
38 | {
39 | use MountableFilesystemTrait;
40 | use FilesystemFlagsImplementationTrait;
41 |
42 | /**
43 | * int (*getattr) (const char *, struct stat *);
44 | */
45 | public function getattr(string $path, Stat $stat): int
46 | {
47 | return -Errno::ENOSYS;
48 | }
49 |
50 | /**
51 | * int (*readlink) (const char *, char *, size_t);
52 | */
53 | public function readlink(string $path, CStringBuffer $buffer, int $size): int
54 | {
55 | return -Errno::ENOSYS;
56 | }
57 |
58 | /**
59 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
60 | *
61 | * @deprecated
62 | */
63 | public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int
64 | {
65 | return -Errno::ENOSYS;
66 | }
67 |
68 | /**
69 | * int (*mknod) (const char *, mode_t, dev_t);
70 | */
71 | public function mknod(string $path, int $mode, int $dev): int
72 | {
73 | return -Errno::ENOSYS;
74 | }
75 |
76 | /**
77 | * int (*mkdir) (const char *, mode_t);
78 | */
79 | public function mkdir(string $path, int $mode): int
80 | {
81 | return -Errno::ENOSYS;
82 | }
83 |
84 | /**
85 | * int (*unlink) (const char *);
86 | */
87 | public function unlink(string $path): int
88 | {
89 | return -Errno::ENOSYS;
90 | }
91 |
92 | /**
93 | * int (*rmdir) (const char *);
94 | */
95 | public function rmdir(string $path): int
96 | {
97 | return -Errno::ENOSYS;
98 | }
99 |
100 | /**
101 | * int (*symlink) (const char *, const char *);
102 | */
103 | public function symlink(string $path, string $link): int
104 | {
105 | return -Errno::ENOSYS;
106 | }
107 |
108 | /**
109 | * int (*rename) (const char *, const char *);
110 | */
111 | public function rename(string $from, string $to): int
112 | {
113 | return -Errno::ENOSYS;
114 | }
115 |
116 | /**
117 | * int (*link) (const char *, const char *);
118 | */
119 | public function link(string $path, string $link): int
120 | {
121 | return -Errno::ENOSYS;
122 | }
123 |
124 | /**
125 | * int (*chmod) (const char *, mode_t);
126 | */
127 | public function chmod(string $path, int $mode): int
128 | {
129 | return -Errno::ENOSYS;
130 | }
131 |
132 | /**
133 | * int (*chown) (const char *, uid_t, gid_t);
134 | */
135 | public function chown(string $path, int $uid, int $gid): int
136 | {
137 | return -Errno::ENOSYS;
138 | }
139 |
140 | /**
141 | * int (*truncate) (const char *, off_t);
142 | */
143 | public function truncate(string $path, int $offset): int
144 | {
145 | return -Errno::ENOSYS;
146 | }
147 |
148 | /**
149 | * int (*utime) (const char *, struct utimbuf *);
150 | */
151 | public function utime(string $path, UtimBuf $utime_buf): int
152 | {
153 | return -Errno::ENOSYS;
154 | }
155 |
156 | /**
157 | * int (*open) (const char *, struct fuse_file_info *);
158 | */
159 | public function open(string $path, FuseFileInfo $fuse_file_info): int
160 | {
161 | return 0;
162 | }
163 |
164 | /**
165 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
166 | */
167 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
168 | {
169 | return -Errno::ENOSYS;
170 | }
171 |
172 | /**
173 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
174 | */
175 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
176 | {
177 | return -Errno::ENOSYS;
178 | }
179 |
180 | /**
181 | * int (*statfs) (const char *, struct statvfs *);
182 | */
183 | public function statfs(string $path, StatVfs $statvfs): int
184 | {
185 | return -Errno::ENOSYS;
186 | }
187 |
188 | /**
189 | * int (*flush) (const char *, struct fuse_file_info *);
190 | */
191 | public function flush(string $path, FuseFileInfo $fuse_file_info): int
192 | {
193 | return -Errno::ENOSYS;
194 | }
195 |
196 | /**
197 | * int (*release) (const char *, struct fuse_file_info *);
198 | */
199 | public function release(string $path, FuseFileInfo $fuse_file_info): int
200 | {
201 | return -Errno::ENOSYS;
202 | }
203 |
204 | /**
205 | * int (*fsync) (const char *, int, struct fuse_file_info *);
206 | */
207 | public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int
208 | {
209 | return -Errno::ENOSYS;
210 | }
211 |
212 | /**
213 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
214 | */
215 | public function setxattr(string $path, string $name, string $value, int $size): int
216 | {
217 | return -Errno::ENOSYS;
218 | }
219 |
220 | /**
221 | * int (*getxattr) (const char *, const char *, char *, size_t);
222 | */
223 | public function getxattr(string $path, string $name, ?string &$value, int $size): int
224 | {
225 | return -Errno::ENOSYS;
226 | }
227 |
228 | /**
229 | * int (*listxattr) (const char *, char *, size_t);*
230 | */
231 | public function listxattr(string $path, ?string &$value, int $size): int
232 | {
233 | return -Errno::ENOSYS;
234 | }
235 |
236 | /**
237 | * int (*removexattr) (const char *, const char *);
238 | */
239 | public function removexattr(string $path, string $name): int
240 | {
241 | return -Errno::ENOSYS;
242 | }
243 |
244 | /**
245 | * int (*opendir) (const char *, struct fuse_file_info *);
246 | */
247 | public function opendir(string $path, FuseFileInfo $fuse_file_info): int
248 | {
249 | return 0;
250 | }
251 |
252 | /**
253 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
254 | */
255 | public function readdir(
256 | string $path,
257 | FuseReadDirBuffer $buf,
258 | FuseFillDir $filler,
259 | int $offset,
260 | FuseFileInfo $fuse_file_info
261 | ): int {
262 | return -Errno::ENOSYS;
263 | }
264 |
265 | /**
266 | * int (*releasedir) (const char *, struct fuse_file_info *);
267 | */
268 | public function releasedir(string $path, FuseFileInfo $fuse_file_info): int
269 | {
270 | return -Errno::ENOSYS;
271 | }
272 |
273 | /**
274 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
275 | */
276 | public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int
277 | {
278 | return -Errno::ENOSYS;
279 | }
280 |
281 | /**
282 | * void *(*init) (struct fuse_conn_info *conn);
283 | */
284 | public function init(FuseConnInfo $conn): ?FusePrivateData
285 | {
286 | return null;
287 | }
288 |
289 | /**
290 | * void (*destroy) (void *);
291 | */
292 | public function destroy(?FusePrivateData $private_data): void
293 | {
294 | }
295 |
296 | /**
297 | * int (*access) (const char *, int);
298 | */
299 | public function access(string $path, int $mode): int
300 | {
301 | return -Errno::ENOSYS;
302 | }
303 |
304 | /**
305 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
306 | */
307 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int
308 | {
309 | return -Errno::ENOSYS;
310 | }
311 |
312 | /**
313 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
314 | */
315 | public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int
316 | {
317 | return -Errno::ENOSYS;
318 | }
319 |
320 | /**
321 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
322 | */
323 | public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int
324 | {
325 | return -Errno::ENOSYS;
326 | }
327 |
328 | /**
329 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
330 | */
331 | public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int
332 | {
333 | return -Errno::ENOSYS;
334 | }
335 |
336 | /**
337 | * int (*utimens) (const char *, const struct timespec tv[2]);
338 | *
339 | * @param TypedCDataArray $tv
340 | */
341 | public function utimens(string $path, TypedCDataArray $tv): int
342 | {
343 | return -Errno::ENOSYS;
344 | }
345 |
346 | /**
347 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
348 | */
349 | public function bmap(string $path, int $blocksize, int &$idx): int
350 | {
351 | return -Errno::ENOSYS;
352 | }
353 |
354 | /**
355 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
356 | */
357 | public function ioctl(
358 | string $path,
359 | int $cmd,
360 | FuseIoctlArgPointer $arg,
361 | FuseFileInfo $fuse_file_info,
362 | int $flags,
363 | FuseIoctlDataPointer $data
364 | ): int {
365 | return -Errno::ENOSYS;
366 | }
367 |
368 | /**
369 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
370 | */
371 | public function poll(
372 | string $path,
373 | FuseFileInfo $fuse_file_info,
374 | FusePollHandle $fuse_pollhandle,
375 | int &$reventsp
376 | ): int {
377 | return -Errno::ENOSYS;
378 | }
379 |
380 | /**
381 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
382 | */
383 | public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int
384 | {
385 | return -Errno::ENOSYS;
386 | }
387 |
388 | /**
389 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
390 | *
391 | * @param TypedCDataArray $bufp
392 | */
393 | public function readBuf(
394 | string $path,
395 | TypedCDataArray $bufp,
396 | int $size,
397 | int $offset,
398 | FuseFileInfo $fuse_file_info
399 | ): int {
400 | return -Errno::ENOSYS;
401 | }
402 |
403 | /**
404 | * int (*flock) (const char *, struct fuse_file_info *, int op);
405 | */
406 | public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int
407 | {
408 | return -Errno::ENOSYS;
409 | }
410 |
411 | /**
412 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
413 | */
414 | public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int
415 | {
416 | return -Errno::ENOSYS;
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/src/FilesystemFlagsImplementationTrait.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | trait FilesystemFlagsImplementationTrait
17 | {
18 | /**
19 | * unsigned int flag_nullpath_ok:1;
20 | * unsigned int flag_nopath:1;
21 | * unsigned int flag_utime_omit_ok:1;
22 | * unsigned int flag_reserved:29;
23 | */
24 | private bool $flag_nullpath_ok = false;
25 | private bool $flag_nopath = false;
26 | private bool $flag_utime_omit_ok = false;
27 |
28 | public function setFlagNullpathOk(bool $flag): void
29 | {
30 | $this->flag_nullpath_ok = $flag;
31 | }
32 |
33 | public function getFlagNullpathOk(): bool
34 | {
35 | return $this->flag_nullpath_ok;
36 | }
37 |
38 | public function setFlagNopath(bool $flag): void
39 | {
40 | $this->flag_nopath = $flag;
41 | }
42 |
43 | public function getFlagNopath(): bool
44 | {
45 | return $this->flag_nopath;
46 | }
47 |
48 | public function setFlagUtimeOmitOk(bool $flag): void
49 | {
50 | $this->flag_utime_omit_ok = $flag;
51 | }
52 |
53 | public function getFlagUtimeOmitOk(): bool
54 | {
55 | return $this->flag_utime_omit_ok;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/FilesystemInterface.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use Fuse\Libc\Fcntl\Flock;
17 | use Fuse\Libc\Fuse\FuseBufVec;
18 | use Fuse\Libc\Fuse\FuseConnInfo;
19 | use Fuse\Libc\Fuse\FuseDirFill;
20 | use Fuse\Libc\Fuse\FuseDirHandle;
21 | use Fuse\Libc\Fuse\FuseFileInfo;
22 | use Fuse\Libc\Fuse\FuseFillDir;
23 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
24 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
25 | use Fuse\Libc\Fuse\FusePollHandle;
26 | use Fuse\Libc\Fuse\FusePrivateData;
27 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
28 | use Fuse\Libc\String\CBytesBuffer;
29 | use Fuse\Libc\String\CStringBuffer;
30 | use Fuse\Libc\Sys\Stat\Stat;
31 | use Fuse\Libc\Sys\StatVfs\StatVfs;
32 | use Fuse\Libc\Time\TimeSpec;
33 | use Fuse\Libc\Utime\UtimBuf;
34 | use TypedCData\TypedCDataArray;
35 |
36 | interface FilesystemInterface extends Mountable
37 | {
38 | /**
39 | * int (*getattr) (const char *, struct stat *);
40 | */
41 | public function getattr(string $path, Stat $stat): int;
42 |
43 | /**
44 | * int (*readlink) (const char *, char *, size_t);
45 | */
46 | public function readlink(string $path, CStringBuffer $buffer, int $size): int;
47 |
48 | /**
49 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
50 | *
51 | * @deprecated
52 | */
53 | public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int;
54 |
55 | /**
56 | * int (*mknod) (const char *, mode_t, dev_t);
57 | */
58 | public function mknod(string $path, int $mode, int $dev): int;
59 |
60 | /**
61 | * int (*mkdir) (const char *, mode_t);
62 | */
63 | public function mkdir(string $path, int $mode): int;
64 |
65 | /**
66 | * int (*unlink) (const char *);
67 | */
68 | public function unlink(string $path): int;
69 |
70 | /**
71 | * int (*rmdir) (const char *);
72 | */
73 | public function rmdir(string $path): int;
74 |
75 | /**
76 | * int (*symlink) (const char *, const char *);
77 | */
78 | public function symlink(string $path, string $link): int;
79 |
80 | /**
81 | * int (*rename) (const char *, const char *);
82 | */
83 | public function rename(string $from, string $to): int;
84 |
85 | /**
86 | * int (*link) (const char *, const char *);
87 | */
88 | public function link(string $path, string $link): int;
89 |
90 | /**
91 | * int (*chmod) (const char *, mode_t);
92 | */
93 | public function chmod(string $path, int $mode): int;
94 |
95 | /**
96 | * int (*chown) (const char *, uid_t, gid_t);
97 | */
98 | public function chown(string $path, int $uid, int $gid): int;
99 |
100 | /**
101 | * int (*truncate) (const char *, off_t);
102 | */
103 | public function truncate(string $path, int $offset): int;
104 |
105 | /**
106 | * int (*utime) (const char *, struct utimbuf *);
107 | */
108 | public function utime(string $path, UtimBuf $utime_buf): int;
109 |
110 | /**
111 | * int (*open) (const char *, struct fuse_file_info *);
112 | */
113 | public function open(string $path, FuseFileInfo $fuse_file_info): int;
114 |
115 | /**
116 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
117 | */
118 | public function read(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int;
119 |
120 | /**
121 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
122 | */
123 | public function write(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int;
124 |
125 | /**
126 | * int (*statfs) (const char *, struct statvfs *);
127 | */
128 | public function statfs(string $path, StatVfs $statvfs): int;
129 |
130 | /**
131 | * int (*flush) (const char *, struct fuse_file_info *);
132 | */
133 | public function flush(string $path, FuseFileInfo $fuse_file_info): int;
134 |
135 | /**
136 | * int (*release) (const char *, struct fuse_file_info *);
137 | */
138 | public function release(string $path, FuseFileInfo $fuse_file_info): int;
139 |
140 | /**
141 | * int (*fsync) (const char *, int, struct fuse_file_info *);
142 | */
143 | public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int;
144 |
145 | /**
146 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
147 | */
148 | public function setxattr(string $path, string $name, string $value, int $size): int;
149 |
150 | /**
151 | * int (*getxattr) (const char *, const char *, char *, size_t);
152 | */
153 | public function getxattr(string $path, string $name, ?string &$value, int $size): int;
154 |
155 | /**
156 | * int (*listxattr) (const char *, char *, size_t);*
157 | */
158 | public function listxattr(string $path, ?string &$value, int $size): int;
159 |
160 | /**
161 | * int (*removexattr) (const char *, const char *);
162 | */
163 | public function removexattr(string $path, string $name): int;
164 |
165 | /**
166 | * int (*opendir) (const char *, struct fuse_file_info *);
167 | */
168 | public function opendir(string $path, FuseFileInfo $fuse_file_info): int;
169 |
170 | /**
171 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
172 | */
173 | public function readdir(
174 | string $path,
175 | FuseReadDirBuffer $buf,
176 | FuseFillDir $filler,
177 | int $offset,
178 | FuseFileInfo $fuse_file_info
179 | ): int;
180 |
181 | /**
182 | * int (*releasedir) (const char *, struct fuse_file_info *);
183 | */
184 | public function releasedir(string $path, FuseFileInfo $fuse_file_info): int;
185 |
186 | /**
187 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
188 | */
189 | public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int;
190 |
191 | /**
192 | * void *(*init) (struct fuse_conn_info *conn);
193 | */
194 | public function init(FuseConnInfo $conn): ?FusePrivateData;
195 |
196 | /**
197 | * void (*destroy) (void *);
198 | */
199 | public function destroy(?FusePrivateData $private_data): void;
200 |
201 | /**
202 | * int (*access) (const char *, int);
203 | */
204 | public function access(string $path, int $mode): int;
205 |
206 | /**
207 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
208 | */
209 | public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int;
210 |
211 | /**
212 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
213 | */
214 | public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int;
215 |
216 | /**
217 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
218 | */
219 | public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int;
220 |
221 | /**
222 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
223 | */
224 | public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int;
225 |
226 | /**
227 | * int (*utimens) (const char *, const struct timespec tv[2]);
228 | *
229 | * @param TypedCDataArray $tv
230 | */
231 | public function utimens(string $path, TypedCDataArray $tv): int;
232 |
233 | /**
234 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
235 | */
236 | public function bmap(string $path, int $blocksize, int &$idx): int;
237 |
238 | /**
239 | * unsigned int flag_nullpath_ok:1;
240 | * unsigned int flag_nopath:1;
241 | * unsigned int flag_utime_omit_ok:1;
242 | * unsigned int flag_reserved:29;
243 | */
244 | public function setFlagNullpathOk(bool $flag): void;
245 | public function getFlagNullpathOk(): bool;
246 | public function setFlagNopath(bool $flag): void;
247 | public function getFlagNopath(): bool;
248 | public function setFlagUtimeOmitOk(bool $flag): void;
249 | public function getFlagUtimeOmitOk(): bool;
250 |
251 | /**
252 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
253 | */
254 | public function ioctl(
255 | string $path,
256 | int $cmd,
257 | FuseIoctlArgPointer $arg,
258 | FuseFileInfo $fuse_file_info,
259 | int $flags,
260 | FuseIoctlDataPointer $data
261 | ): int;
262 |
263 | /**
264 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
265 | */
266 | public function poll(
267 | string $path,
268 | FuseFileInfo $fuse_file_info,
269 | FusePollHandle $fuse_pollhandle,
270 | int &$reventsp
271 | ): int;
272 |
273 | /**
274 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
275 | */
276 | public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int;
277 |
278 | /**
279 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
280 | *
281 | * @param TypedCDataArray $bufp
282 | */
283 | public function readBuf(
284 | string $path,
285 | TypedCDataArray $bufp,
286 | int $size,
287 | int $offset,
288 | FuseFileInfo $fuse_file_info
289 | ): int;
290 |
291 | /**
292 | * int (*flock) (const char *, struct fuse_file_info *, int op);
293 | */
294 | public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int;
295 |
296 | /**
297 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
298 | */
299 | public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int;
300 | }
301 |
--------------------------------------------------------------------------------
/src/Fuse.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use FFI;
17 | use FFI\CData;
18 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
19 |
20 | final class Fuse
21 | {
22 | private static ?self $instance;
23 | /** @var FuseFFI */
24 | public FFI $ffi;
25 |
26 | /**
27 | * @param FuseFFI $ffi
28 | */
29 | private function __construct(FFI $ffi)
30 | {
31 | $this->ffi = $ffi;
32 | }
33 |
34 | /**
35 | * @return FuseFFI
36 | */
37 | private static function load(): FFI
38 | {
39 | /** @var FuseFFI */
40 | return FFI::cdef(
41 | file_get_contents(__DIR__ . '/Headers/fuse.h'),
42 | 'libfuse.so'
43 | );
44 | }
45 |
46 | public static function getInstance(): self
47 | {
48 | if (!isset(self::$instance)) {
49 | self::$instance = new self(self::load());
50 | }
51 | return self::$instance;
52 | }
53 |
54 | /**
55 | * @param list $args
56 | * @param FuseOperations $fuse_operations
57 | * @param CData|null $user_data
58 | * @return int
59 | */
60 | public function main(array $args, FuseOperations $fuse_operations, ?CData $user_data = null): int
61 | {
62 | $argc = count($args);
63 | /** @var \FFI\CDataArray $argv_real */
64 | $argv_real = FFI::new('char *[' . count($args) . ']');
65 | foreach ($args as $key => $item) {
66 | $item_len = strlen($item);
67 | $item_len_nul = $item_len + 1;
68 | /** @var \FFI\CDataArray $argv_item */
69 | $argv_item = FFI::new("char[{$item_len_nul}]", false, true);
70 | FFI::memcpy($argv_item, $item, $item_len);
71 | $argv_item[$item_len] = "\0";
72 | $argv_real[$key] = $argv_item;
73 | }
74 |
75 | return Fuse::getInstance()->ffi->fuse_main_real(
76 | $argc,
77 | $argv_real,
78 | FFI::addr($fuse_operations->getCData()),
79 | $fuse_operations->getSize(),
80 | $user_data
81 | );
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/FuseLogicException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | /** @deprecated */
17 | class FuseLogicException extends \LogicException
18 | {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/FuseOperations.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use FFI;
17 | use FFI\CData;
18 | use Fuse\Libc\Fcntl\Flock;
19 | use Fuse\Libc\Fuse\FuseBufVec;
20 | use Fuse\Libc\Fuse\FuseConnInfo;
21 | use Fuse\Libc\Fuse\FuseDirFill;
22 | use Fuse\Libc\Fuse\FuseDirHandle;
23 | use Fuse\Libc\Fuse\FuseFileInfo;
24 | use Fuse\Libc\Fuse\FuseFillDir;
25 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
26 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
27 | use Fuse\Libc\Fuse\FusePollHandle;
28 | use Fuse\Libc\Fuse\FusePrivateData;
29 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
30 | use Fuse\Libc\String\CBytesBuffer;
31 | use Fuse\Libc\String\CStringBuffer;
32 | use Fuse\Libc\Sys\Stat\Stat;
33 | use Fuse\Libc\Sys\StatVfs\StatVfs;
34 | use Fuse\Libc\Time\TimeSpec;
35 | use Fuse\Libc\Utime\UtimBuf;
36 | use ReflectionClass;
37 | use TypedCData\TypedCDataArray;
38 | use TypedCData\TypedCDataWrapper;
39 |
40 | // phpcs:disable Generic.Files.LineLength
41 | /**
42 | * @psalm-type TimeSpecArray = TypedCDataArray
43 | * @psalm-type FuseBufVecArray = TypedCDataArray
44 | * @psalm-type getattr_op = callable(string $path, CData $stat): int
45 | * @psalm-type getattr_typed_op = callable(string $path, Stat $stat): int
46 | * @psalm-type readlink_op = callable(string $path, CData $buffer, int $size): int
47 | * @psalm-type readlink_typed_op = callable(string $path, CStringBuffer $buffer, int $size): int
48 | * @psalm-type getdir_op = callable(string $path, CData $dirhandle, CData $dirfill): int
49 | * @psalm-type getdir_typed_op = callable(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int
50 | * @psalm-type utime_op = callable(string $path, CData $utime_buf): int
51 | * @psalm-type utime_typed_op = callable(string $path, UtimBuf $utime_buf): int
52 | * @psalm-type open_op = callable(string $path, CData $fuse_file_info): int
53 | * @psalm-type open_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
54 | * @psalm-type read_op = callable(string $path, CData $buffer, int $size, int $offset, CData $fuse_file_info): int
55 | * @psalm-type read_typed_op = callable(string $path, CBytesBuffer $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
56 | * @psalm-type write_op = callable(string $path, string $buffer, int $size, int $offset, CData $fuse_file_info): int
57 | * @psalm-type write_typed_op = callable(string $path, string $buffer, int $size, int $offset, FuseFileInfo $fuse_file_info): int
58 | * @psalm-type statfs_op = callable(string $path, CData $statvfs): int
59 | * @psalm-type statfs_typed_op = callable(string $path, StatVfs $statvfs): int
60 | * @psalm-type flush_op = callable(string $path, CData $fuse_file_info): int
61 | * @psalm-type flush_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
62 | * @psalm-type release_op = callable(string $path, CData $fuse_file_info): int
63 | * @psalm-type release_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
64 | * @psalm-type fsync_op = callable(string $path, int $flags, CData $fuse_file_info): int
65 | * @psalm-type fsync_typed_op = callable(string $path, int $flags, FuseFileInfo $fuse_file_info): int
66 | * @psalm-type opendir_op = callable(string $path, CData $fuse_file_info): int
67 | * @psalm-type opendir_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
68 | * @psalm-type readdir_op = callable(string $path, CData $buf, CData $filler, int $offset, CData $fuse_file_info): int
69 | * @psalm-type readdir_typed_op = callable(string $path, FuseReadDirBuffer $buf, FuseFillDir $filler, int $offset, FuseFileInfo $fuse_file_info): int
70 | * @psalm-type releasedir_op = callable(string $path, CData $fuse_file_info): int
71 | * @psalm-type releasedir_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
72 | * @psalm-type fsyncdir_op = callable(string $path, CData $fuse_file_info): int
73 | * @psalm-type fsyncdir_typed_op = callable(string $path, FuseFileInfo $fuse_file_info): int
74 | * @psalm-type init_op = callable(CData $conn): ?CData
75 | * @psalm-type init_typed_op = callable(FuseConnInfo $conn): ?FusePrivateData
76 | * @psalm-type destroy_op = callable(CData $private_data): void
77 | * @psalm-type destroy_typed_op = callable(?FusePrivateData$private_data): void
78 | * @psalm-type create_op = callable(string $path, int $mode, CData $fuse_file_info): int
79 | * @psalm-type create_typed_op = callable(string $path, int $mode, FuseFileInfo $fuse_file_info): int
80 | * @psalm-type ftruncate_op = callable(string $path, int $offset, CData $fuse_file_info): int
81 | * @psalm-type ftruncate_typed_op = callable(string $path, int $offset, FuseFileInfo $fuse_file_info): int
82 | * @psalm-type fgetattr_op = callable(string $path, CData $stat, CData $fuse_file_info): int
83 | * @psalm-type fgetattr_typed_op = callable(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int
84 | * @psalm-type lock_op = callable(string $path, CData $fuse_file_info, int $cmd, CData $flock): int
85 | * @psalm-type lock_typed_op = callable(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int
86 | * @psalm-type utimens_op = callable(string $path, CData $tv): int
87 | * @psalm-type utimens_typed_op = callable(string $path, TimeSpecArray$tv): int
88 | * @psalm-type bmap_op = callable(string $path, int $blocksize, CData $idx): int
89 | * @psalm-type bmap_typed_op = callable(string $path, int $blocksize, int $idx): int
90 | * @psalm-type ioctl_op = callable(string $path, int $cmd, CData $arg, CData $fuse_file_info, int $flags, CData $data): int
91 | * @psalm-type ioctl_typed_op = callable(string $path, int $cmd, FuseIoctlArgPointer $arg, FuseFileInfo $fuse_file_info, int $flags, FuseIoctlDataPointer $data): int
92 | * @psalm-type poll_op = callable(string $path, CData $fuse_file_info, CData $fuse_pollhandle, int $reventsp): int
93 | * @psalm-type poll_typed_op = callable(string $path, FuseFileInfo $fuse_file_info, FusePollHandle $fuse_pollhandle, int $reventsp): int
94 | * @psalm-type write_buf_op = callable(string $path, CData $buf, int $offset, CData $fuse_file_info): int
95 | * @psalm-type write_buf_typed_op = callable(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int
96 | * @psalm-type read_buf_op = callable(string $path, CData $bufp, int $size, int $offset, CData $fuse_file_info): int
97 | * @psalm-type read_buf_typed_op = callable(string $path, FuseBufVecArray $bufp, int $size, int $offset, FuseFileInfo $fuse_file_info): int
98 | * @psalm-type flock_op = callable(string $path, CData $fuse_file_info, int $op): int
99 | * @psalm-type flock_typed_op = callable(string $path, FuseFileInfo $fuse_file_info, int $op): int
100 | * @psalm-type fallocate_op = callable(string $path, int $mode, int $offset, CData $fuse_file_info): int
101 | * @psalm-type fallocate_typed_op = callable(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int
102 | */
103 | // phpcs:enable Generic.Files.LineLength
104 | final class FuseOperations implements Mountable
105 | {
106 | /**
107 | * int (*getattr) (const char *, struct stat *);
108 | *
109 | * @var null|getattr_op|getattr_typed_op
110 | */
111 | public $getattr = null;
112 |
113 | /**
114 | * int (*readlink) (const char *, char *, size_t);
115 | *
116 | * @var null|readlink_op|readlink_typed_op
117 | */
118 | public $readlink = null;
119 |
120 | /**
121 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
122 | *
123 | * @deprecated
124 | * @var null|getdir_op|getdir_typed_op
125 | */
126 | public $getdir = null;
127 |
128 | /**
129 | * int (*mknod) (const char *, mode_t, dev_t);
130 | *
131 | * @var null|callable(string $path, int $mode, int $dev): int
132 | */
133 | public $mknod = null;
134 |
135 | /**
136 | * int (*mkdir) (const char *, mode_t);
137 | *
138 | * @var null|callable(string $path, int $mode): int
139 | */
140 | public $mkdir = null;
141 |
142 | /**
143 | * int (*unlink) (const char *);
144 | *
145 | * @var null|callable(string $path): int
146 | */
147 | public $unlink = null;
148 |
149 | /**
150 | * int (*rmdir) (const char *);
151 | *
152 | * @var null|callable(string $path): int
153 | */
154 | public $rmdir = null;
155 |
156 | /**
157 | * int (*symlink) (const char *, const char *);
158 | *
159 | * @var null|callable(string $path, string $link): int
160 | */
161 | public $symlink = null;
162 |
163 | /**
164 | * int (*rename) (const char *, const char *);
165 | *
166 | * @var null|callable(string $from, string $to): int
167 | */
168 | public $rename = null;
169 |
170 | /**
171 | * int (*link) (const char *, const char *);
172 | *
173 | * @var null|callable(string $path, string $link): int
174 | */
175 | public $link = null;
176 |
177 | /**
178 | * int (*chmod) (const char *, mode_t);
179 | *
180 | * @var null|callable(string $path, int $mode): int
181 | */
182 | public $chmod = null;
183 |
184 | /**
185 | * int (*chown) (const char *, uid_t, gid_t);
186 | *
187 | * @var null|callable(string $path, int $uid, int $gid): int
188 | */
189 | public $chown = null;
190 |
191 | /**
192 | * int (*truncate) (const char *, off_t);
193 | *
194 | * @var null|callable(string $path, int $offset): int
195 | */
196 | public $truncate = null;
197 |
198 | /**
199 | * int (*utime) (const char *, struct utimbuf *);
200 | *
201 | * @var null|utime_op|utime_typed_op
202 | */
203 | public $utime = null;
204 |
205 | /**
206 | * int (*open) (const char *, struct fuse_file_info *);
207 | *
208 | * @var null|open_op|open_typed_op
209 | */
210 | public $open = null;
211 |
212 | /**
213 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
214 | *
215 | * @var null|read_op|read_typed_op
216 | */
217 | public $read = null;
218 |
219 | /**
220 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
221 | *
222 | * @var null|write_op|write_typed_op
223 | */
224 | public $write = null;
225 |
226 | /**
227 | * int (*statfs) (const char *, struct statvfs *);
228 | *
229 | * @var null|statfs_op|statfs_typed_op
230 | */
231 | public $statfs = null;
232 |
233 | /**
234 | * int (*flush) (const char *, struct fuse_file_info *);
235 | *
236 | * @var null|flush_op|flush_typed_op
237 | */
238 | public $flush = null;
239 |
240 | /**
241 | * int (*release) (const char *, struct fuse_file_info *);
242 | *
243 | * @var null|release_op|release_typed_op
244 | */
245 | public $release = null;
246 |
247 | /**
248 | * int (*fsync) (const char *, int, struct fuse_file_info *);
249 | *
250 | * @var null|fsync_op|fsync_typed_op
251 | */
252 | public $fsync = null;
253 |
254 | /**
255 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
256 | *
257 | * @var null|callable(string $path, string $name, string $value, int $size): int
258 | */
259 | public $setxattr = null;
260 |
261 | /**
262 | * int (*getxattr) (const char *, const char *, char *, size_t);
263 | *
264 | * @var null|callable(string $path, string $name, string $value, int $size): int
265 | */
266 | public $getxattr = null;
267 |
268 | /**
269 | * int (*listxattr) (const char *, char *, size_t);
270 | *
271 | * @var null|callable(string $path, string $value, int $size): int
272 | */
273 | public $listxattr = null;
274 |
275 | /**
276 | * int (*removexattr) (const char *, const char *);
277 | *
278 | * @var null|callable(string $size, string $name): int
279 | */
280 | public $removexattr = null;
281 |
282 | /**
283 | * int (*opendir) (const char *, struct fuse_file_info *);
284 | *
285 | * @var null|opendir_op|opendir_typed_op
286 | */
287 | public $opendir = null;
288 |
289 | /**
290 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
291 | *
292 | * @var null|readdir_op|readdir_typed_op
293 | */
294 | public $readdir = null;
295 |
296 | /**
297 | * int (*releasedir) (const char *, struct fuse_file_info *);
298 | *
299 | * @var null|releasedir_op|releasedir_typed_op
300 | */
301 | public $releasedir = null;
302 |
303 | /**
304 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
305 | *
306 | * @var null|fsyncdir_op|fsyncdir_typed_op
307 | */
308 | public $fsyncdir = null;
309 |
310 | /**
311 | * void *(*init) (struct fuse_conn_info *conn);
312 | *
313 | * @var null|init_op|init_typed_op
314 | */
315 | public $init = null;
316 |
317 | /**
318 | * void (*destroy) (void *);
319 | *
320 | * @var null|destroy_op|destroy_typed_op
321 | */
322 | public $destroy = null;
323 |
324 | /**
325 | * int (*access) (const char *, int);
326 | *
327 | * @var null|callable(string $path, int $mode): int
328 | */
329 | public $access = null;
330 |
331 | /**
332 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
333 | *
334 | * @var null|create_op|create_typed_op
335 | */
336 | public $create = null;
337 |
338 | /**
339 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
340 | *
341 | * @var null|ftruncate_op|ftruncate_typed_op
342 | */
343 | public $ftruncate = null;
344 |
345 | /**
346 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
347 | *
348 | * @var null|fgetattr_op|fgetattr_typed_op
349 | */
350 | public $fgetattr = null;
351 |
352 | /**
353 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
354 | *
355 | * @var null|lock_op|lock_typed_op
356 | */
357 | public $lock = null;
358 |
359 | /**
360 | * int (*utimens) (const char *, const struct timespec tv[2]);
361 | *
362 | * @var null|utimens_op|utimens_typed_op
363 | */
364 | public $utimens = null;
365 |
366 | /**
367 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
368 | *
369 | * @var null|bmap_op|bmap_typed_op
370 | */
371 | public $bmap = null;
372 |
373 | /**
374 | * unsigned int flag_nullpath_ok:1;
375 | * unsigned int flag_nopath:1;
376 | * unsigned int flag_utime_omit_ok:1;
377 | * unsigned int flag_reserved:29;
378 | */
379 | public bool $flag_nullpath_ok = false;
380 | public bool $flag_nopath = false;
381 | public bool $flag_utime_omit_ok = false;
382 |
383 | /**
384 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
385 | *
386 | * @var null|ioctl_op|ioctl_typed_op
387 | */
388 | public $ioctl = null;
389 |
390 | /**
391 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
392 | *
393 | * @var null|poll_op|poll_typed_op
394 | */
395 | public $poll = null;
396 |
397 | /**
398 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
399 | *
400 | * @var null|write_buf_op|write_buf_typed_op
401 | */
402 | public $write_buf = null;
403 |
404 | /**
405 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
406 | *
407 | * @var null|read_buf_op|read_buf_typed_op
408 | */
409 | public $read_buf = null;
410 |
411 | /**
412 | * int (*flock) (const char *, struct fuse_file_info *, int op);
413 | *
414 | * @var null|flock_op|flock_typed_op
415 | */
416 | public $flock = null;
417 |
418 | /**
419 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
420 | *
421 | * @var null|fallocate_op|fallocate_typed_op
422 | */
423 | public $fallocate = null;
424 |
425 | private ?CData $cdata_cache = null;
426 |
427 |
428 | public function getCData(): CData
429 | {
430 | $fuse_operations = Fuse::getInstance()->ffi->new('struct fuse_operations');
431 | $typed_cdata_wrapper = new TypedCDataWrapper();
432 | /**
433 | * @psalm-suppress RawObjectIteration
434 | * @var string $name
435 | * @var callable|null|bool $callable
436 | */
437 | foreach ($this as $name => $callable) {
438 | if (is_null($callable)) {
439 | continue;
440 | }
441 | if (substr_compare($name, 'flag_', 0, 5) === 0) {
442 | continue;
443 | }
444 | assert(is_callable($callable));
445 | $fuse_operations->$name = $typed_cdata_wrapper->createWrapper($callable);
446 | }
447 | assert(!is_null($fuse_operations));
448 | return $this->cdata_cache = $fuse_operations;
449 | }
450 |
451 | public function getSize(): int
452 | {
453 | $typename = 'struct fuse_operations';
454 | $type = Fuse::getInstance()->ffi->type(
455 | $typename
456 | );
457 | assert(!is_null($type));
458 | $size = FFI::sizeof(
459 | $type
460 | );
461 | return $size;
462 | }
463 |
464 | public function getOperations(): FuseOperations
465 | {
466 | return $this;
467 | }
468 | }
469 |
--------------------------------------------------------------------------------
/src/Headers/fuse.h:
--------------------------------------------------------------------------------
1 | typedef unsigned int mode_t;
2 | typedef unsigned long int dev_t;
3 | typedef unsigned long int ino_t;
4 | typedef long int off_t;
5 | typedef long int nlink_t;
6 | typedef unsigned int uid_t;
7 | typedef unsigned int gid_t;
8 | typedef int pid_t;
9 | typedef long int blksize_t;
10 | typedef long int blkcnt_t;
11 | typedef unsigned long int fsblkcnt64_t;
12 | typedef unsigned long int uint64_t;
13 |
14 | struct timespec
15 | {
16 | long tv_sec;
17 | long tv_nsec;
18 | };
19 |
20 | struct utimbuf
21 | {
22 | long actime;
23 | long modtime;
24 | };
25 |
26 | struct stat
27 | {
28 | dev_t st_dev;
29 | ino_t st_ino;
30 | nlink_t st_nlink;
31 | mode_t st_mode;
32 | uid_t st_uid;
33 | gid_t st_gid;
34 | int __pad0;
35 | dev_t st_rdev;
36 | off_t st_size;
37 | blksize_t st_blksize;
38 | blkcnt_t st_blocks;
39 | struct timespec st_atim;
40 | struct timespec st_mtim;
41 | struct timespec st_ctim;
42 | long int reserved[3];
43 | };
44 |
45 | struct fuse_file_info
46 | {
47 | int flags;
48 | unsigned long fh_old;
49 | int writepage;
50 | unsigned int direct_io : 1;
51 | unsigned int keep_cache : 1;
52 | unsigned int flush : 1;
53 | unsigned int nonseekable : 1;
54 | unsigned int flock_release : 1;
55 | unsigned int padding : 27;
56 | uint64_t fh;
57 | uint64_t lock_owner;
58 | };
59 |
60 | struct statvfs
61 | {
62 | unsigned long int f_bsize;
63 | unsigned long int f_frsize;
64 | fsblkcnt64_t f_blocks;
65 | fsblkcnt64_t f_bfree;
66 | fsblkcnt64_t f_bavail;
67 | fsblkcnt64_t f_files;
68 | fsblkcnt64_t f_ffree;
69 | fsblkcnt64_t f_favail;
70 | unsigned long int f_fsid;
71 | unsigned long int f_flag;
72 | unsigned long int f_namemax;
73 | int __f_spare[6];
74 | };
75 |
76 | struct fuse_conn_info {
77 | unsigned proto_major;
78 | unsigned proto_minor;
79 | unsigned async_read;
80 | unsigned max_write;
81 | unsigned max_readahead;
82 | unsigned capable;
83 | unsigned want;
84 | unsigned max_background;
85 | unsigned congestion_threshold;
86 | unsigned reserved[23];
87 | };
88 |
89 | struct flock
90 | {
91 | short int l_type;
92 | short int l_whence;
93 | off_t l_start;
94 | off_t l_len;
95 | pid_t l_pid;
96 | };
97 |
98 | enum fuse_buf_flags
99 | {
100 | FUSE_BUF_IS_FD = (1 << 1),
101 | FUSE_BUF_FD_SEEK = (1 << 2),
102 | FUSE_BUF_FD_RETRY = (1 << 3),
103 | };
104 |
105 | struct fuse_buf
106 | {
107 | size_t size;
108 | enum fuse_buf_flags flags;
109 | void *mem;
110 | int fd;
111 | off_t pos;
112 | };
113 |
114 | struct fuse_bufvec
115 | {
116 | size_t count;
117 | size_t idx;
118 | size_t off;
119 | struct fuse_buf buf[1];
120 | };
121 |
122 | struct fuse;
123 | struct fuse_cmd;
124 | struct fuse_pollhandle;
125 |
126 | typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off);
127 | typedef struct fuse_dirhandle *fuse_dirh_t;
128 | typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type, ino_t ino);
129 | struct fuse_operations
130 | {
131 | int (*getattr) (const char *, struct stat *);
132 | int (*readlink) (const char *, char *, size_t);
133 | int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
134 | int (*mknod) (const char *, mode_t, dev_t);
135 | int (*mkdir) (const char *, mode_t);
136 | int (*unlink) (const char *);
137 | int (*rmdir) (const char *);
138 | int (*symlink) (const char *, const char *);
139 | int (*rename) (const char *, const char *);
140 | int (*link) (const char *, const char *);
141 | int (*chmod) (const char *, mode_t);
142 | int (*chown) (const char *, uid_t, gid_t);
143 | int (*truncate) (const char *, off_t);
144 | int (*utime) (const char *, struct utimbuf *);
145 | int (*open) (const char *, struct fuse_file_info *);
146 | int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
147 | int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
148 | int (*statfs) (const char *, struct statvfs *);
149 | int (*flush) (const char *, struct fuse_file_info *);
150 | int (*release) (const char *, struct fuse_file_info *);
151 | int (*fsync) (const char *, int, struct fuse_file_info *);
152 | int (*setxattr) (const char *, const char *, const char *, size_t, int);
153 | int (*getxattr) (const char *, const char *, char *, size_t);
154 | int (*listxattr) (const char *, char *, size_t);
155 | int (*removexattr) (const char *, const char *);
156 | int (*opendir) (const char *, struct fuse_file_info *);
157 | int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
158 | int (*releasedir) (const char *, struct fuse_file_info *);
159 | int (*fsyncdir) (const char *, int, struct fuse_file_info *);
160 | void *(*init) (struct fuse_conn_info *conn);
161 | void (*destroy) (void *);
162 | int (*access) (const char *, int);
163 | int (*create) (const char *, mode_t, struct fuse_file_info *);
164 | int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
165 | int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
166 | int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
167 | int (*utimens) (const char *, const struct timespec tv[2]);
168 | int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
169 | unsigned int flag_nullpath_ok:1;
170 | unsigned int flag_nopath:1;
171 | unsigned int flag_utime_omit_ok:1;
172 | unsigned int flag_reserved:29;
173 | int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
174 | int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
175 | int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
176 | int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
177 | int (*flock) (const char *, struct fuse_file_info *, int op);
178 | int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
179 | };
180 |
181 | int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, size_t op_size, void *user_data);
182 |
183 | typedef unsigned long fuse_ino_t;
184 | typedef struct fuse_req *fuse_req_t;
185 | struct fuse_entry_param
186 | {
187 | fuse_ino_t ino;
188 | unsigned long generation;
189 | struct stat attr;
190 | double attr_timeout;
191 | double entry_timeout;
192 | };
193 | struct fuse_forget_data
194 | {
195 | uint64_t ino;
196 | uint64_t nlookup;
197 | };
198 |
199 | struct fuse_lowlevel_ops
200 | {
201 | void (*init) (void *userdata, struct fuse_conn_info *conn);
202 | void (*destroy) (void *userdata);
203 | void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
204 | void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
205 | void (*getattr) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
206 | void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi);
207 | void (*readlink) (fuse_req_t req, fuse_ino_t ino);
208 | void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev);
209 | void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode);
210 | void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name);
211 | void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name);
212 | void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, const char *name);
213 | void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname);
214 | void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname);
215 | void (*open) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
216 | void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi);
217 | void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi);
218 | void (*flush) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
219 | void (*release) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
220 | void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi);
221 | void (*opendir) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
222 | void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi);
223 | void (*releasedir) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
224 | void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi);
225 | void (*statfs) (fuse_req_t req, fuse_ino_t ino);
226 | void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags);
227 | void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size);
228 | void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size);
229 | void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name);
230 | void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
231 | void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info *fi);
232 | void (*getlk) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock);
233 | void (*setlk) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep);
234 | void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, uint64_t idx);
235 | void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, struct fuse_file_info *fi, unsigned flags, const void *in_buf, size_t in_bufsz, size_t out_bufsz);
236 | void (*poll) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct fuse_pollhandle *ph);
237 | void (*write_buf) (fuse_req_t req, fuse_ino_t ino, struct fuse_bufvec *bufv, off_t off, struct fuse_file_info *fi);
238 | void (*retrieve_reply) (fuse_req_t req, void *cookie, fuse_ino_t ino, off_t offset, struct fuse_bufvec *bufv);
239 | void (*forget_multi) (fuse_req_t req, size_t count, struct fuse_forget_data *forgets);
240 | void (*flock) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, int op);
241 | void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t length, struct fuse_file_info *fi);
242 | };
243 |
244 | struct fuse_session;
245 | struct fuse_chan;
246 | struct fuse_args
247 | {
248 | int argc;
249 | char **argv;
250 | int allocated;
251 | };
252 | enum fuse_buf_copy_flags
253 | {
254 | FUSE_BUF_NO_SPLICE = (1 << 1),
255 | FUSE_BUF_FORCE_SPLICE = (1 << 2),
256 | FUSE_BUF_SPLICE_MOVE = (1 << 3),
257 | FUSE_BUF_SPLICE_NONBLOCK= (1 << 4),
258 | };
259 | struct iovec
260 | {
261 | void *iov_base;
262 | size_t iov_len;
263 | };
264 | struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata);
265 |
266 | int fuse_reply_err(fuse_req_t req, int err);
267 |
268 | void fuse_reply_none(fuse_req_t req);
269 |
270 | int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e);
271 |
272 | int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
273 | const struct fuse_file_info *fi);
274 |
275 | int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
276 | double attr_timeout);
277 |
278 | int fuse_reply_readlink(fuse_req_t req, const char *link);
279 |
280 | int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi);
281 |
282 | int fuse_reply_write(fuse_req_t req, size_t count);
283 |
284 | int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size);
285 |
286 | int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
287 | enum fuse_buf_copy_flags flags);
288 |
289 | int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count);
290 |
291 | int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf);
292 |
293 | int fuse_reply_xattr(fuse_req_t req, size_t count);
294 |
295 | int fuse_reply_lock(fuse_req_t req, const struct flock *lock);
296 |
297 | int fuse_reply_bmap(fuse_req_t req, uint64_t idx);
298 |
299 | size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
300 | const char *name, const struct stat *stbuf,
301 | off_t off);
302 | int fuse_reply_ioctl_retry(fuse_req_t req,
303 | const struct iovec *in_iov, size_t in_count,
304 | const struct iovec *out_iov, size_t out_count);
305 |
306 | int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
307 |
308 | int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
309 | int count);
310 |
311 | int fuse_reply_poll(fuse_req_t req, unsigned revents);
312 |
313 | int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph);
314 |
315 | int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
316 | off_t off, off_t len);
317 |
318 | int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
319 | const char *name, size_t namelen);
320 |
321 | int fuse_lowlevel_notify_delete(struct fuse_chan *ch,
322 | fuse_ino_t parent, fuse_ino_t child,
323 | const char *name, size_t namelen);
324 |
325 | int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino,
326 | off_t offset, struct fuse_bufvec *bufv,
327 | enum fuse_buf_copy_flags flags);
328 | int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino,
329 | size_t size, off_t offset, void *cookie);
330 |
331 | void *fuse_req_userdata(fuse_req_t req);
332 |
333 | int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
334 | int *multithreaded, int *foreground);
335 |
336 | struct fuse_session_ops
337 | {
338 | void (*process) (void *data, const char *buf, size_t len,
339 | struct fuse_chan *ch);
340 | void (*exit) (void *data, int val);
341 | int (*exited) (void *data);
342 | void (*destroy) (void *data);
343 | };
344 | struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data);
345 | size_t fuse_buf_size(const struct fuse_bufvec *bufv);
346 |
347 | ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src,
348 | enum fuse_buf_copy_flags flags);
349 |
350 | int fuse_set_signal_handlers(struct fuse_session *se);
351 |
352 | void fuse_remove_signal_handlers(struct fuse_session *se);
353 |
354 | int fuse_daemonize(int foreground);
355 |
356 | int fuse_version(void);
357 |
358 | void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
359 |
360 | void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
361 |
362 | void fuse_session_remove_chan(struct fuse_chan *ch);
363 |
364 | struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
365 | struct fuse_chan *ch);
366 |
367 | void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
368 | struct fuse_chan *ch);
369 |
370 | void fuse_session_process_buf(struct fuse_session *se,
371 | const struct fuse_buf *buf, struct fuse_chan *ch);
372 |
373 | int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
374 | struct fuse_chan **chp);
375 |
376 | void fuse_session_destroy(struct fuse_session *se);
377 |
378 | void fuse_session_exit(struct fuse_session *se);
379 |
380 | void fuse_session_reset(struct fuse_session *se);
381 |
382 | int fuse_session_exited(struct fuse_session *se);
383 |
384 | void *fuse_session_data(struct fuse_session *se);
385 | struct fuse_opt
386 | {
387 | const char *templ;
388 | unsigned long offset;
389 | int value;
390 | };
391 | typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
392 | struct fuse_args *outargs);
393 |
394 | int fuse_opt_parse(struct fuse_args *args, void *data,
395 | const struct fuse_opt opts[], fuse_opt_proc_t proc);
396 |
397 | int fuse_opt_add_opt(char **opts, const char *opt);
398 |
399 | int fuse_opt_add_opt_escaped(char **opts, const char *opt);
400 |
401 | int fuse_opt_add_arg(struct fuse_args *args, const char *arg);
402 |
403 | int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg);
404 |
405 | void fuse_opt_free_args(struct fuse_args *args);
406 |
407 | struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args);
408 |
409 | void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
410 |
411 | int fuse_session_loop(struct fuse_session *se);
412 |
413 | int fuse_session_loop_mt(struct fuse_session *se);
--------------------------------------------------------------------------------
/src/Libc/Errno/Errno.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Errno;
15 |
16 | final class Errno
17 | {
18 | public const ENOENT = 2;
19 | public const ENOTDIR = 20;
20 | public const ENOSYS = 38;
21 | }
22 |
--------------------------------------------------------------------------------
/src/Libc/Fcntl/Flock.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fcntl;
15 |
16 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * struct flock
21 | * {
22 | * short int l_type;
23 | * short int l_whence;
24 | * off_t l_start;
25 | * off_t l_len;
26 | * pid_t l_pid;
27 | * };
28 | */
29 | final class Flock implements TypedCDataInterface
30 | {
31 | use TypedCDataDefaultImplementationTrait;
32 |
33 | public int $l_type;
34 | public int $l_whence;
35 | public int $l_start;
36 | public int $l_len;
37 | public int $l_pid;
38 |
39 | /**
40 | * Flock constructor.
41 | * @param int $l_type
42 | * @param int $l_whence
43 | * @param int $l_start
44 | * @param int $l_len
45 | * @param int $l_pid
46 | */
47 | public function __construct(
48 | int $l_type = 0,
49 | int $l_whence = 0,
50 | int $l_start = 0,
51 | int $l_len = 0,
52 | int $l_pid = 0
53 | ) {
54 | $this->l_type = $l_type;
55 | $this->l_whence = $l_whence;
56 | $this->l_start = $l_start;
57 | $this->l_len = $l_len;
58 | $this->l_pid = $l_pid;
59 | }
60 |
61 | public static function getCTypeName(): string
62 | {
63 | return 'struct flock';
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseBuf.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
18 | use TypedCData\TypedCDataInterface;
19 |
20 | /**
21 | * struct fuse_buf
22 | * {
23 | * size_t size;
24 | * enum fuse_buf_flags flags;
25 | * void *mem;
26 | * int fd;
27 | * off_t pos;
28 | * };
29 | */
30 | final class FuseBuf implements TypedCDataInterface
31 | {
32 | use TypedCDataDefaultImplementationTrait;
33 |
34 | public int $size;
35 | public int $flags;
36 | public ?CData $mem;
37 | public int $fd;
38 | public int $pos;
39 |
40 | public static function getCTypeName(): string
41 | {
42 | return 'struct fuse_buf';
43 | }
44 |
45 | public function __construct(
46 | int $size = 0,
47 | int $flags = 0,
48 | ?CData $mem = null,
49 | int $fd = 0,
50 | int $pos = 0
51 | ) {
52 | $this->size = $size;
53 | $this->flags = $flags;
54 | $this->mem = $mem;
55 | $this->fd = $fd;
56 | $this->pos = $pos;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseBufVec.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
17 | use TypedCData\TypedCDataArray;
18 | use TypedCData\TypedCDataInterface;
19 |
20 | /**
21 | * struct fuse_bufvec
22 | * {
23 | * size_t count;
24 | * size_t idx;
25 | * size_t off;
26 | * struct fuse_buf buf[1];
27 | * };
28 | */
29 | final class FuseBufVec implements TypedCDataInterface
30 | {
31 | use TypedCDataDefaultImplementationTrait;
32 |
33 | public int $count;
34 | public int $idx;
35 | public int $off;
36 | /** @var TypedCDataArray */
37 | public TypedCDataArray $buf;
38 |
39 | /**
40 | * @param int $count
41 | * @param int $idx
42 | * @param int $off
43 | * @param TypedCDataArray|null $buf
44 | */
45 | public function __construct(
46 | int $count = 0,
47 | int $idx = 0,
48 | int $off = 0,
49 | ?TypedCDataArray $buf = null
50 | ) {
51 | $this->count = $count;
52 | $this->idx = $idx;
53 | $this->off = $off;
54 | /** @var \FFI\CDataArray $fuse_buf */
55 | $fuse_buf = FuseBuf::newCData();
56 | $this->buf = $buf ?? new TypedCDataArray(
57 | $fuse_buf,
58 | FuseBuf::class
59 | );
60 | }
61 |
62 | public static function getCTypeName(): string
63 | {
64 | return 'struct fuse_bufvec';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseConnInfo.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
18 | use TypedCData\TypedCDataInterface;
19 |
20 | /**
21 | * struct fuse_conn_info
22 | * {
23 | * unsigned proto_major;
24 | * unsigned proto_minor;
25 | * unsigned async_read;
26 | * unsigned max_write;
27 | * unsigned max_readahead;
28 | * unsigned capable;
29 | * unsigned want;
30 | * unsigned max_background;
31 | * unsigned congestion_threshold;
32 | * unsigned reserved[23];
33 | * };
34 | */
35 | final class FuseConnInfo implements TypedCDataInterface
36 | {
37 | use TypedCDataDefaultImplementationTrait;
38 |
39 | public int $proto_major;
40 | public int $proto_minor;
41 | public int $async_read;
42 | public int $max_write;
43 | public int $max_readahead;
44 | public int $capable;
45 | public int $want;
46 | public int $max_background;
47 | public int $congestion_threshold;
48 | public ?CData $reserved;
49 |
50 | public static function getCTypeName(): string
51 | {
52 | return 'struct fuse_conn_info';
53 | }
54 |
55 | public function __construct(
56 | int $proto_major = 0,
57 | int $proto_minor = 0,
58 | int $async_read = 0,
59 | int $max_write = 0,
60 | int $max_readahead = 0,
61 | int $capable = 0,
62 | int $want = 0,
63 | int $max_background = 0,
64 | int $congestion_threshold = 0,
65 | ?CData $reserved = null
66 | ) {
67 | $this->proto_major = $proto_major;
68 | $this->proto_minor = $proto_minor;
69 | $this->async_read = $async_read;
70 | $this->max_write = $max_write;
71 | $this->max_readahead = $max_readahead;
72 | $this->capable = $capable;
73 | $this->want = $want;
74 | $this->max_background = $max_background;
75 | $this->congestion_threshold = $congestion_threshold;
76 | $this->reserved = $reserved;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseDirFill.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type, ino_t ino);
21 | */
22 | final class FuseDirFill implements TypedCDataInterface
23 | {
24 | /** @var \Fuse\FuseDirFillCData */
25 | private CData $cdata;
26 |
27 | public function __invoke(FuseDirHandle $dirhandle, string $name, int $type, int $ino): int
28 | {
29 | /** @var int */
30 | return ($this->cdata)($dirhandle->toCData(null), $name, $type, $ino);
31 | }
32 |
33 | public static function getCTypeName(): string
34 | {
35 | return 'fuse_dirfil_t';
36 | }
37 |
38 | /** @param \Fuse\FuseDirFillCData $cdata */
39 | public function __construct(CData $cdata)
40 | {
41 | $this->cdata = $cdata;
42 | }
43 |
44 | /** @return self */
45 | public static function fromCData(CData $cdata): self
46 | {
47 | /** @var \Fuse\FuseDirFillCData $cdata */
48 | return new self($cdata);
49 | }
50 |
51 | public function toCData(CData $cdata): CData
52 | {
53 | return $cdata;
54 | }
55 |
56 | public static function newCData(): CData
57 | {
58 | throw new \LogicException();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseDirHandle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * typedef struct fuse_dirhandle *fuse_dirh_t;
21 | */
22 | final class FuseDirHandle implements TypedCDataInterface
23 | {
24 | private CData $cdata;
25 |
26 | public static function getCTypeName(): string
27 | {
28 | return 'struct fuse_dirhandle *';
29 | }
30 |
31 | public function __construct(CData $cdata)
32 | {
33 | $this->cdata = $cdata;
34 | }
35 |
36 | /** @return static */
37 | public static function fromCData(CData $cdata): TypedCDataInterface
38 | {
39 | return new self($cdata);
40 | }
41 |
42 | public function toCData(?CData $cdata): CData
43 | {
44 | return $this->cdata;
45 | }
46 |
47 | public static function newCData(): CData
48 | {
49 | throw new \LogicException('this type doesn\'t support creation of CData');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseFileInfo.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * struct fuse_file_info
21 | * {
22 | * int flags;
23 | * unsigned long fh_old;
24 | * int writepage;
25 | * unsigned int direct_io : 1;
26 | * unsigned int keep_cache : 1;
27 | * unsigned int flush : 1;
28 | * unsigned int nonseekable : 1;
29 | * unsigned int flock_release : 1;
30 | * unsigned int padding : 27;
31 | * uint64_t fh;
32 | * uint64_t lock_owner;
33 | * };
34 | */
35 | final class FuseFileInfo implements TypedCDataInterface
36 | {
37 | use TypedCDataDefaultImplementationTrait;
38 |
39 | public int $flags = 0;
40 | public int $fh_old = 0;
41 | public int $writepage = 0;
42 | public int $direct_io = 0;
43 | public int $keep_cache = 0;
44 | public int $nonseekable = 0;
45 | public int $flock_release = 0;
46 | public int $padding = 0;
47 | public int $fh = 0;
48 | public int $lock_owner = 0;
49 |
50 | public static function getCTypeName(): string
51 | {
52 | return 'struct fuse_file_info';
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseFillDir.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use Fuse\Libc\Sys\Stat\Stat;
18 | use TypedCData\TypedCDataInterface;
19 |
20 | /**
21 | * typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off);
22 | */
23 | final class FuseFillDir implements TypedCDataInterface
24 | {
25 | /** @var \Fuse\FuseFillDirCData */
26 | private CData $cdata;
27 |
28 | public function __invoke(FuseReadDirBuffer $buf, string $name, ?Stat $stbuf, int $off): int
29 | {
30 | if (!is_null($stbuf)) {
31 | $stbuf = $stbuf->toCData($stbuf->newCData());
32 | }
33 | /** @var int */
34 | return ($this->cdata)($buf->toCData(null), $name, $stbuf, $off);
35 | }
36 |
37 | public static function getCTypeName(): string
38 | {
39 | return 'fuse_fill_dir_t';
40 | }
41 |
42 | /** @param \Fuse\FuseFillDirCData $cdata */
43 | public function __construct(CData $cdata)
44 | {
45 | $this->cdata = $cdata;
46 | }
47 |
48 | /** @return static */
49 | public static function fromCData(CData $cdata): self
50 | {
51 | /** @var \Fuse\FuseFillDirCData $cdata */
52 | return new self($cdata);
53 | }
54 |
55 | public function toCData(CData $cdata): CData
56 | {
57 | return $cdata;
58 | }
59 |
60 | public static function newCData(): CData
61 | {
62 | throw new \LogicException('this type doesn\'t support creation of CData');
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseIoctlArgPointer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class FuseIoctlArgPointer implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public static function getCTypeName(): string
24 | {
25 | return 'void *';
26 | }
27 |
28 | public function __construct(CData $cdata)
29 | {
30 | $this->cdata = $cdata;
31 | }
32 |
33 | /** @return static */
34 | public static function fromCData(CData $cdata): TypedCDataInterface
35 | {
36 | return new self($cdata);
37 | }
38 |
39 | public function toCData(?CData $cdata): CData
40 | {
41 | return $this->cdata;
42 | }
43 |
44 | public static function newCData(): CData
45 | {
46 | throw new \LogicException('this type doesn\'t support creation of CData');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseIoctlDataPointer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class FuseIoctlDataPointer implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public static function getCTypeName(): string
24 | {
25 | return 'void *';
26 | }
27 |
28 | public function __construct(CData $cdata)
29 | {
30 | $this->cdata = $cdata;
31 | }
32 |
33 | /** @return static */
34 | public static function fromCData(CData $cdata): TypedCDataInterface
35 | {
36 | return new self($cdata);
37 | }
38 |
39 | public function toCData(?CData $cdata): CData
40 | {
41 | return $this->cdata;
42 | }
43 |
44 | public static function newCData(): CData
45 | {
46 | throw new \LogicException('this type doesn\'t support creation of CData');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FusePollHandle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * struct fuse_pollhandle *;
21 | */
22 | final class FusePollHandle implements TypedCDataInterface
23 | {
24 | private CData $cdata;
25 |
26 | public static function getCTypeName(): string
27 | {
28 | return 'struct fuse_pollhandle *';
29 | }
30 |
31 | public function __construct(CData $cdata)
32 | {
33 | $this->cdata = $cdata;
34 | }
35 |
36 | /** @return static */
37 | public static function fromCData(CData $cdata): TypedCDataInterface
38 | {
39 | return new self($cdata);
40 | }
41 |
42 | public function toCData(?CData $cdata): CData
43 | {
44 | return $this->cdata;
45 | }
46 |
47 | public static function newCData(): CData
48 | {
49 | throw new \LogicException('this type doesn\'t support creation of CData');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FusePrivateData.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class FusePrivateData implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public static function getCTypeName(): string
24 | {
25 | return 'void *';
26 | }
27 |
28 | public function __construct(CData $cdata)
29 | {
30 | $this->cdata = $cdata;
31 | }
32 |
33 | /** @return static */
34 | public static function fromCData(CData $cdata): TypedCDataInterface
35 | {
36 | return new self($cdata);
37 | }
38 |
39 | public function toCData(?CData $cdata): CData
40 | {
41 | return $this->cdata;
42 | }
43 |
44 | public static function newCData(): CData
45 | {
46 | throw new \LogicException('this type doesn\'t support creation of CData');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Libc/Fuse/FuseReadDirBuffer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Fuse;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class FuseReadDirBuffer implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public static function getCTypeName(): string
24 | {
25 | return 'void *';
26 | }
27 |
28 | public function __construct(CData $cdata)
29 | {
30 | $this->cdata = $cdata;
31 | }
32 |
33 | /** @return static */
34 | public static function fromCData(CData $cdata): TypedCDataInterface
35 | {
36 | return new self($cdata);
37 | }
38 |
39 | public function toCData(?CData $cdata): CData
40 | {
41 | return $this->cdata;
42 | }
43 |
44 | public static function newCData(): CData
45 | {
46 | throw new \LogicException('this type doesn\'t support creation of CData');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Libc/String/CBytesBuffer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\String;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class CBytesBuffer implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public function __construct(CData $cdata)
24 | {
25 | $this->cdata = $cdata;
26 | }
27 |
28 | /** @return static */
29 | public static function fromCData(CData $cdata): self
30 | {
31 | return new self($cdata);
32 | }
33 |
34 | public static function getCTypeName(): string
35 | {
36 | return 'char *';
37 | }
38 |
39 | public function write(string $content, int $size): void
40 | {
41 | \FFI::memcpy($this->cdata, $content, $size);
42 | }
43 |
44 | public function toCData(CData $cdata): CData
45 | {
46 | return $cdata;
47 | }
48 |
49 | public static function newCData(): CData
50 | {
51 | /** @var CData */
52 | return \FFI::new('char[1]');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Libc/String/CStringBuffer.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\String;
15 |
16 | use FFI\CData;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | final class CStringBuffer implements TypedCDataInterface
20 | {
21 | private CData $cdata;
22 |
23 | public function __construct(CData $cdata)
24 | {
25 | $this->cdata = $cdata;
26 | }
27 |
28 | /** @return static */
29 | public static function fromCData(CData $cdata): self
30 | {
31 | return new self($cdata);
32 | }
33 |
34 | public static function getCTypeName(): string
35 | {
36 | return 'char *';
37 | }
38 |
39 | public function toCData(CData $cdata): CData
40 | {
41 | return $cdata;
42 | }
43 |
44 | public static function newCData(): CData
45 | {
46 | /** @var CData */
47 | return \FFI::new('char[1]');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Libc/Sys/Stat/Stat.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Sys\Stat;
15 |
16 | use FFI\CData;
17 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
18 | use Fuse\Libc\Time\TimeSpec;
19 | use TypedCData\TypedCDataInterface;
20 |
21 | /**
22 | * struct stat
23 | * {
24 | * dev_t st_dev;
25 | * ino_t st_ino;
26 | * nlink_t st_nlink;
27 | * mode_t st_mode;
28 | * uid_t st_uid;
29 | * gid_t st_gid;
30 | * int __pad0;
31 | * dev_t st_rdev;
32 | * off_t st_size;
33 | * blksize_t st_blksize;
34 | * blkcnt_t st_blocks;
35 | * struct timespec st_atim;
36 | * struct timespec st_mtim;
37 | * struct timespec st_ctim;
38 | * long int reserved[3];
39 | * };
40 | */
41 | final class Stat implements TypedCDataInterface
42 | {
43 | use TypedCDataDefaultImplementationTrait;
44 |
45 | public const S_IFDIR = 0040000;
46 | public const S_IFREG = 0100000;
47 |
48 | public static function getCTypeName(): string
49 | {
50 | return 'struct stat';
51 | }
52 |
53 | public int $st_dev;
54 | public int $st_ino;
55 | public int $st_nlink;
56 | public int $st_mode;
57 | public int $st_uid;
58 | public int $st_gid;
59 | // phpcs:ignore PSR2.Classes.PropertyDeclaration
60 | public int $__pad0;
61 | public int $st_rdev;
62 | public int $st_size;
63 | public int $st_blksize;
64 | public int $st_blocks;
65 | public TimeSpec $st_atim;
66 | public TimeSpec $st_mtim;
67 | public TimeSpec $st_ctim;
68 | public ?CData $reserved;
69 |
70 | public function __construct(
71 | int $st_dev = 0,
72 | int $st_ino = 0,
73 | int $st_nlink = 0,
74 | int $st_mode = 0,
75 | int $st_uid = 0,
76 | int $st_gid = 0,
77 | int $__pad0 = 0,
78 | int $st_rdev = 0,
79 | int $st_size = 0,
80 | int $st_blksize = 0,
81 | int $st_blocks = 0,
82 | ?TimeSpec $st_atim = null,
83 | ?TimeSpec $st_mtim = null,
84 | ?TimeSpec $st_ctim = null,
85 | ?CData $reserved = null
86 | ) {
87 | $this->st_dev = $st_dev;
88 | $this->st_ino = $st_ino;
89 | $this->st_nlink = $st_nlink;
90 | $this->st_mode = $st_mode;
91 | $this->st_uid = $st_uid;
92 | $this->st_gid = $st_gid;
93 | $this->__pad0 = $__pad0;
94 | $this->st_rdev = $st_rdev;
95 | $this->st_size = $st_size;
96 | $this->st_blksize = $st_blksize;
97 | $this->st_blocks = $st_blocks;
98 | $this->st_atim = $st_atim ?? new TimeSpec();
99 | $this->st_mtim = $st_mtim ?? new TimeSpec();
100 | $this->st_ctim = $st_ctim ?? new TimeSpec();
101 | $this->reserved = $reserved;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Libc/Sys/StatVfs/StatVfs.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Sys\StatVfs;
15 |
16 | use FFI\CData;
17 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
18 | use TypedCData\TypedCDataInterface;
19 |
20 | /**
21 | * struct statvfs
22 | * {
23 | * unsigned long int f_bsize;
24 | * unsigned long int f_frsize;
25 | * fsblkcnt64_t f_blocks;
26 | * fsblkcnt64_t f_bfree;
27 | * fsblkcnt64_t f_bavail;
28 | * fsblkcnt64_t f_files;
29 | * fsblkcnt64_t f_ffree;
30 | * fsblkcnt64_t f_favail;
31 | * unsigned long int f_fsid;
32 | * unsigned long int f_flag;
33 | * unsigned long int f_namemax;
34 | * int __f_spare[6];
35 | * };
36 | */
37 | final class StatVfs implements TypedCDataInterface
38 | {
39 | use TypedCDataDefaultImplementationTrait;
40 |
41 | public int $f_bsize;
42 | public int $f_frsize;
43 | public int $f_blocks;
44 | public int $f_bfree;
45 | public int $f_bavail;
46 | public int $f_files;
47 | public int $f_ffree;
48 | public int $f_favail;
49 | public int $f_fsid;
50 | public int $f_flag;
51 | public int $f_namemax;
52 | // phpcs:ignore PSR2.Classes.PropertyDeclaration
53 | public ?CData $__f_spare;
54 |
55 | public function __construct(
56 | int $f_bsize = 0,
57 | int $f_frsize = 0,
58 | int $f_blocks = 0,
59 | int $f_bfree = 0,
60 | int $f_bavail = 0,
61 | int $f_files = 0,
62 | int $f_ffree = 0,
63 | int $f_favail = 0,
64 | int $f_fsid = 0,
65 | int $f_flag = 0,
66 | int $f_namemax = 0,
67 | ?CData $__f_spare = null
68 | ) {
69 | $this->f_bsize = $f_bsize;
70 | $this->f_frsize = $f_frsize;
71 | $this->f_blocks = $f_blocks;
72 | $this->f_bfree = $f_bfree;
73 | $this->f_bavail = $f_bavail;
74 | $this->f_files = $f_files;
75 | $this->f_ffree = $f_ffree;
76 | $this->f_favail = $f_favail;
77 | $this->f_fsid = $f_fsid;
78 | $this->f_flag = $f_flag;
79 | $this->f_namemax = $f_namemax;
80 | $this->__f_spare = $__f_spare;
81 | }
82 |
83 | public static function getCTypeName(): string
84 | {
85 | return 'struct statvfs *';
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Libc/Time/TimeSpec.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Time;
15 |
16 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * struct timespec
21 | * {
22 | * long tv_sec;
23 | * long tv_nsec;
24 | * };
25 | */
26 | final class TimeSpec implements TypedCDataInterface
27 | {
28 | use TypedCDataDefaultImplementationTrait;
29 |
30 | public int $tv_sec = 0;
31 | public int $tv_nsec = 0;
32 |
33 | public static function getCTypeName(): string
34 | {
35 | return 'struct timespec';
36 | }
37 |
38 | public function __construct(int $tv_sec = 0, int $tv_nsec = 0)
39 | {
40 | $this->tv_sec = $tv_sec;
41 | $this->tv_nsec = $tv_nsec;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Libc/Utime/UtimBuf.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Libc\Utime;
15 |
16 | use Fuse\FFI\TypedCDataDefaultImplementationTrait;
17 | use TypedCData\TypedCDataInterface;
18 |
19 | /**
20 | * struct utimbuf
21 | * {
22 | * long actime;
23 | * long modtime;
24 | * };
25 | */
26 | final class UtimBuf implements TypedCDataInterface
27 | {
28 | use TypedCDataDefaultImplementationTrait;
29 |
30 | public int $actime;
31 | public int $modtime;
32 |
33 | public static function getCTypeName(): string
34 | {
35 | return 'struct utimbuf';
36 | }
37 |
38 | public function __construct(int $actime = 0, int $modtime = 0)
39 | {
40 | $this->actime = $actime;
41 | $this->modtime = $modtime;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Mountable.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | interface Mountable
17 | {
18 | public function getOperations(): FuseOperations;
19 | }
20 |
--------------------------------------------------------------------------------
/src/MountableFilesystemTrait.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use Fuse\Libc\Fcntl\Flock;
17 | use Fuse\Libc\Fuse\FuseBufVec;
18 | use Fuse\Libc\Fuse\FuseConnInfo;
19 | use Fuse\Libc\Fuse\FuseDirFill;
20 | use Fuse\Libc\Fuse\FuseDirHandle;
21 | use Fuse\Libc\Fuse\FuseFileInfo;
22 | use Fuse\Libc\Fuse\FuseFillDir;
23 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
24 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
25 | use Fuse\Libc\Fuse\FusePollHandle;
26 | use Fuse\Libc\Fuse\FusePrivateData;
27 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
28 | use Fuse\Libc\String\CBytesBuffer;
29 | use Fuse\Libc\String\CStringBuffer;
30 | use Fuse\Libc\Sys\Stat\Stat;
31 | use Fuse\Libc\Sys\StatVfs\StatVfs;
32 | use Fuse\Libc\Time\TimeSpec;
33 | use Fuse\Libc\Utime\UtimBuf;
34 | use TypedCData\TypedCDataArray;
35 |
36 | trait MountableFilesystemTrait
37 | {
38 | public function getOperations(): FuseOperations
39 | {
40 | $fuse_operations = new FuseOperations();
41 |
42 | $fuse_operations->getattr = [$this, 'getattr'];
43 | $fuse_operations->readlink = [$this, 'readlink'];
44 | /** @psalm-suppress DeprecatedProperty */
45 | $fuse_operations->getdir = [$this, 'getdir'];
46 | $fuse_operations->mknod = [$this, 'mknod'];
47 | $fuse_operations->mkdir = [$this, 'mkdir'];
48 | $fuse_operations->unlink = [$this, 'unlink'];
49 | $fuse_operations->rmdir = [$this, 'rmdir'];
50 | $fuse_operations->symlink = [$this, 'symlink'];
51 | $fuse_operations->rename = [$this, 'rename'];
52 | $fuse_operations->link = [$this, 'link'];
53 | $fuse_operations->chmod = [$this, 'chmod'];
54 | $fuse_operations->chown = [$this, 'chown'];
55 | $fuse_operations->truncate = [$this, 'truncate'];
56 | $fuse_operations->utime = [$this, 'utime'];
57 | $fuse_operations->open = [$this, 'open'];
58 | $fuse_operations->read = [$this, 'read'];
59 | $fuse_operations->write = [$this, 'write'];
60 | $fuse_operations->statfs = [$this, 'statfs'];
61 | $fuse_operations->flush = [$this, 'flush'];
62 | $fuse_operations->release = [$this, 'release'];
63 | $fuse_operations->fsync = [$this, 'fsync'];
64 | $fuse_operations->setxattr = [$this, 'setxattr'];
65 | $fuse_operations->getxattr = [$this, 'getxattr'];
66 | $fuse_operations->listxattr = [$this, 'listxattr'];
67 | $fuse_operations->removexattr = [$this, 'removexattr'];
68 | $fuse_operations->opendir = [$this, 'opendir'];
69 | $fuse_operations->readdir = [$this, 'readdir'];
70 | $fuse_operations->releasedir = [$this, 'releasedir'];
71 | $fuse_operations->fsyncdir = [$this, 'fsyncdir'];
72 | $fuse_operations->init = [$this, 'init'];
73 | $fuse_operations->destroy = [$this, 'destroy'];
74 | $fuse_operations->access = [$this, 'access'];
75 | $fuse_operations->create = [$this, 'create'];
76 | $fuse_operations->ftruncate = [$this, 'ftruncate'];
77 | $fuse_operations->fgetattr = [$this, 'fgetattr'];
78 | $fuse_operations->lock = [$this, 'lock'];
79 | $fuse_operations->utimens = [$this, 'utimens'];
80 | $fuse_operations->bmap = [$this, 'bmap'];
81 | $fuse_operations->ioctl = [$this, 'ioctl'];
82 | $fuse_operations->poll = [$this, 'poll'];
83 | $fuse_operations->write_buf = [$this, 'writeBuf'];
84 | $fuse_operations->read_buf = [$this, 'readBuf'];
85 | $fuse_operations->flock = [$this, 'flock'];
86 | $fuse_operations->fallocate = [$this, 'fallocate'];
87 | $fuse_operations->flag_nullpath_ok = $this->getFlagNullpathOk();
88 | $fuse_operations->flag_nopath = $this->getFlagNopath();
89 | $fuse_operations->flag_utime_omit_ok = $this->getFlagUtimeOmitOk();
90 |
91 | return $fuse_operations;
92 | }
93 |
94 | /**
95 | * int (*getattr) (const char *, struct stat *);
96 | */
97 | abstract public function getattr(string $path, Stat $stat): int;
98 |
99 | /**
100 | * int (*readlink) (const char *, char *, size_t);
101 | */
102 | abstract public function readlink(string $path, CStringBuffer $buffer, int $size): int;
103 |
104 | /**
105 | * int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
106 | *
107 | * @deprecated
108 | */
109 | abstract public function getdir(string $path, FuseDirHandle $dirhandle, FuseDirFill $dirfill): int;
110 |
111 | /**
112 | * int (*mknod) (const char *, mode_t, dev_t);
113 | */
114 | abstract public function mknod(string $path, int $mode, int $dev): int;
115 |
116 | /**
117 | * int (*mkdir) (const char *, mode_t);
118 | */
119 | abstract public function mkdir(string $path, int $mode): int;
120 |
121 | /**
122 | * int (*unlink) (const char *);
123 | */
124 | abstract public function unlink(string $path): int;
125 |
126 | /**
127 | * int (*rmdir) (const char *);
128 | */
129 | abstract public function rmdir(string $path): int;
130 |
131 | /**
132 | * int (*symlink) (const char *, const char *);
133 | */
134 | abstract public function symlink(string $path, string $link): int;
135 |
136 | /**
137 | * int (*rename) (const char *, const char *);
138 | */
139 | abstract public function rename(string $from, string $to): int;
140 |
141 | /**
142 | * int (*link) (const char *, const char *);
143 | */
144 | abstract public function link(string $path, string $link): int;
145 |
146 | /**
147 | * int (*chmod) (const char *, mode_t);
148 | */
149 | abstract public function chmod(string $path, int $mode): int;
150 |
151 | /**
152 | * int (*chown) (const char *, uid_t, gid_t);
153 | */
154 | abstract public function chown(string $path, int $uid, int $gid): int;
155 |
156 | /**
157 | * int (*truncate) (const char *, off_t);
158 | */
159 | abstract public function truncate(string $path, int $offset): int;
160 |
161 | /**
162 | * int (*utime) (const char *, struct utimbuf *);
163 | */
164 | abstract public function utime(string $path, UtimBuf $utime_buf): int;
165 |
166 | /**
167 | * int (*open) (const char *, struct fuse_file_info *);
168 | */
169 | abstract public function open(string $path, FuseFileInfo $fuse_file_info): int;
170 |
171 | /**
172 | * int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
173 | */
174 | abstract public function read(
175 | string $path,
176 | CBytesBuffer $buffer,
177 | int $size,
178 | int $offset,
179 | FuseFileInfo $fuse_file_info
180 | ): int;
181 |
182 | /**
183 | * int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
184 | */
185 | abstract public function write(
186 | string $path,
187 | string $buffer,
188 | int $size,
189 | int $offset,
190 | FuseFileInfo $fuse_file_info
191 | ): int;
192 |
193 | /**
194 | * int (*statfs) (const char *, struct statvfs *);
195 | */
196 | abstract public function statfs(string $path, StatVfs $statvfs): int;
197 |
198 | /**
199 | * int (*flush) (const char *, struct fuse_file_info *);
200 | */
201 | abstract public function flush(string $path, FuseFileInfo $fuse_file_info): int;
202 |
203 | /**
204 | * int (*release) (const char *, struct fuse_file_info *);
205 | */
206 | abstract public function release(string $path, FuseFileInfo $fuse_file_info): int;
207 |
208 | /**
209 | * int (*fsync) (const char *, int, struct fuse_file_info *);
210 | */
211 | abstract public function fsync(string $path, int $flags, FuseFileInfo $fuse_file_info): int;
212 |
213 | /**
214 | * int (*setxattr) (const char *, const char *, const char *, size_t, int);
215 | */
216 | abstract public function setxattr(string $path, string $name, string $value, int $size): int;
217 |
218 | /**
219 | * int (*getxattr) (const char *, const char *, char *, size_t);
220 | */
221 | abstract public function getxattr(string $path, string $name, ?string &$value, int $size): int;
222 |
223 | /**
224 | * int (*listxattr) (const char *, char *, size_t);*
225 | */
226 | abstract public function listxattr(string $path, ?string &$value, int $size): int;
227 |
228 | /**
229 | * int (*removexattr) (const char *, const char *);
230 | */
231 | abstract public function removexattr(string $path, string $name): int;
232 |
233 | /**
234 | * int (*opendir) (const char *, struct fuse_file_info *);
235 | */
236 | abstract public function opendir(string $path, FuseFileInfo $fuse_file_info): int;
237 |
238 | /**
239 | * int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *);
240 | */
241 | abstract public function readdir(
242 | string $path,
243 | FuseReadDirBuffer $buf,
244 | FuseFillDir $filler,
245 | int $offset,
246 | FuseFileInfo $fuse_file_info
247 | ): int;
248 |
249 | /**
250 | * int (*releasedir) (const char *, struct fuse_file_info *);
251 | */
252 | abstract public function releasedir(string $path, FuseFileInfo $fuse_file_info): int;
253 |
254 | /**
255 | * int (*fsyncdir) (const char *, int, struct fuse_file_info *);
256 | */
257 | abstract public function fsyncdir(string $path, FuseFileInfo $fuse_file_info): int;
258 |
259 | /**
260 | * void *(*init) (struct fuse_conn_info *conn);
261 | */
262 | abstract public function init(FuseConnInfo $conn): ?FusePrivateData;
263 |
264 | /**
265 | * void (*destroy) (void *);
266 | */
267 | abstract public function destroy(?FusePrivateData $private_data): void;
268 |
269 | /**
270 | * int (*access) (const char *, int);
271 | */
272 | abstract public function access(string $path, int $mode): int;
273 |
274 | /**
275 | * int (*create) (const char *, mode_t, struct fuse_file_info *);
276 | */
277 | abstract public function create(string $path, int $mode, FuseFileInfo $fuse_file_info): int;
278 |
279 | /**
280 | * int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
281 | */
282 | abstract public function ftruncate(string $path, int $offset, FuseFileInfo $fuse_file_info): int;
283 |
284 | /**
285 | * int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
286 | */
287 | abstract public function fgetattr(string $path, Stat $stat, FuseFileInfo $fuse_file_info): int;
288 |
289 | /**
290 | * int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
291 | */
292 | abstract public function lock(string $path, FuseFileInfo $fuse_file_info, int $cmd, Flock $flock): int;
293 |
294 | /**
295 | * int (*utimens) (const char *, const struct timespec tv[2]);
296 | *
297 | * @param TypedCDataArray $tv
298 | */
299 | abstract public function utimens(string $path, TypedCDataArray $tv): int;
300 |
301 | /**
302 | * int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
303 | */
304 | abstract public function bmap(string $path, int $blocksize, int &$idx): int;
305 |
306 | /**
307 | * unsigned int flag_nullpath_ok:1;
308 | * unsigned int flag_nopath:1;
309 | * unsigned int flag_utime_omit_ok:1;
310 | * unsigned int flag_reserved:29;
311 | */
312 | abstract public function setFlagNullpathOk(bool $flag): void;
313 | abstract public function getFlagNullpathOk(): bool;
314 | abstract public function setFlagNopath(bool $flag): void;
315 | abstract public function getFlagNopath(): bool;
316 | abstract public function setFlagUtimeOmitOk(bool $flag): void;
317 | abstract public function getFlagUtimeOmitOk(): bool;
318 |
319 | /**
320 | * int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
321 | */
322 | abstract public function ioctl(
323 | string $path,
324 | int $cmd,
325 | FuseIoctlArgPointer $arg,
326 | FuseFileInfo $fuse_file_info,
327 | int $flags,
328 | FuseIoctlDataPointer $data
329 | ): int;
330 |
331 | /**
332 | * int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
333 | */
334 | abstract public function poll(
335 | string $path,
336 | FuseFileInfo $fuse_file_info,
337 | FusePollHandle $fuse_pollhandle,
338 | int &$reventsp
339 | ): int;
340 |
341 | /**
342 | * int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
343 | */
344 | abstract public function writeBuf(string $path, FuseBufVec $buf, int $offset, FuseFileInfo $fuse_file_info): int;
345 |
346 | /**
347 | * int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
348 | *
349 | * @param TypedCDataArray $bufp
350 | */
351 | abstract public function readBuf(
352 | string $path,
353 | TypedCDataArray $bufp,
354 | int $size,
355 | int $offset,
356 | FuseFileInfo $fuse_file_info
357 | ): int;
358 |
359 | /**
360 | * int (*flock) (const char *, struct fuse_file_info *, int op);
361 | */
362 | abstract public function flock(string $path, FuseFileInfo $fuse_file_info, int $op): int;
363 |
364 | /**
365 | * int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
366 | */
367 | abstract public function fallocate(string $path, int $mode, int $offset, FuseFileInfo $fuse_file_info): int;
368 | }
369 |
--------------------------------------------------------------------------------
/src/Mounter.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | class Mounter
17 | {
18 | private Fuse $fuse;
19 |
20 | public function __construct(?Fuse $fuse = null)
21 | {
22 | $this->fuse = $fuse ?? Fuse::getInstance();
23 | }
24 |
25 | /**
26 | * @param string $path
27 | * @param Mountable $mountable
28 | * @param list|null $args
29 | * @return int
30 | */
31 | public function mount(string $path, Mountable $mountable, array $args = null): int
32 | {
33 | $args ??= [
34 | '',
35 | '-s',
36 | '-f',
37 | $path
38 | ];
39 | return $this->fuse->main($args, $mountable->getOperations());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/FFI/TypedCDataWrapperTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\FFI;
15 |
16 | use Fuse\Fuse;
17 | use Fuse\Libc\Fuse\FuseBufVec;
18 | use Fuse\Libc\Sys\Stat\Stat;
19 | use PHPUnit\Framework\TestCase;
20 | use TypedCData\TypedCDataWrapper;
21 |
22 | class TypedCDataWrapperTest extends TestCase
23 | {
24 | public function testCreateWrapperStat()
25 | {
26 | $test_class = new class () {
27 | public function testMethod(Stat $stat): void
28 | {
29 | $stat->st_blocks = 123;
30 | }
31 | };
32 | $wrapper_creator = new TypedCDataWrapper();
33 | $wrapper = $wrapper_creator->createWrapper([$test_class, 'testMethod']);
34 | $cdata_stat = Fuse::getInstance()->ffi->new(Stat::getCTypeName());
35 | $wrapper($cdata_stat);
36 | $this->assertSame(123, $cdata_stat->st_blocks);
37 | }
38 |
39 | public function testCreateWrapperFuseBufVec()
40 | {
41 | $test_class = new class ($this) {
42 | private TestCase $test_case;
43 | public function __construct(TestCase $test_case)
44 | {
45 | $this->test_case = $test_case;
46 | }
47 | public function testMethod(FuseBufVec $fuse_buf_vec): void
48 | {
49 | $this->test_case->assertSame(789, $fuse_buf_vec->buf[0]->size);
50 | $fuse_buf_vec->count = 123;
51 | $fuse_buf_vec->buf[0]->size = 456;
52 | }
53 | };
54 | $wrapper_creator = new TypedCDataWrapper();
55 | $wrapper = $wrapper_creator->createWrapper([$test_class, 'testMethod']);
56 | $cdata_stat = Fuse::getInstance()->ffi->new(FuseBufVec::getCTypeName());
57 | $cdata_stat->buf[0]->size = 789;
58 | $wrapper($cdata_stat);
59 | $this->assertSame(123, $cdata_stat->count);
60 | $this->assertSame(456, $cdata_stat->buf[0]->size);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/tests/Filesystem/Log/LogUnimplementedFilesystemTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem\Log;
15 |
16 | use FFI;
17 | use Fuse\Filesystem\Null\NullFilesystem;
18 | use Fuse\FilesystemDefaultImplementationTrait;
19 | use Fuse\FilesystemInterface;
20 | use Fuse\Libc\Fcntl\Flock;
21 | use Fuse\Libc\Fuse\FuseBufVec;
22 | use Fuse\Libc\Fuse\FuseConnInfo;
23 | use Fuse\Libc\Fuse\FuseDirFill;
24 | use Fuse\Libc\Fuse\FuseDirHandle;
25 | use Fuse\Libc\Fuse\FuseFileInfo;
26 | use Fuse\Libc\Fuse\FuseFillDir;
27 | use Fuse\Libc\Fuse\FuseIoctlArgPointer;
28 | use Fuse\Libc\Fuse\FuseIoctlDataPointer;
29 | use Fuse\Libc\Fuse\FusePollHandle;
30 | use Fuse\Libc\Fuse\FuseReadDirBuffer;
31 | use Fuse\Libc\String\CBytesBuffer;
32 | use Fuse\Libc\String\CStringBuffer;
33 | use Fuse\Libc\Sys\Stat\Stat;
34 | use Fuse\Libc\Sys\StatVfs\StatVfs;
35 | use Fuse\Libc\Time\TimeSpec;
36 | use Fuse\Libc\Utime\UtimBuf;
37 | use PHPUnit\Framework\TestCase;
38 | use Psr\Log\LoggerInterface;
39 | use Psr\Log\LoggerTrait;
40 | use TypedCData\TypedCDataArray;
41 |
42 | final class LogUnimplementedFilesystemTest extends TestCase
43 | {
44 | public function testDoesNotLogImplemented()
45 | {
46 | $filesystem = new class implements FilesystemInterface {
47 | use FilesystemDefaultImplementationTrait;
48 |
49 | public function getattr(string $path, Stat $stat): int
50 | {
51 | return 42;
52 | }
53 | };
54 |
55 | $sut = new LogUnimplementedFilesystem(
56 | $filesystem,
57 | new class ($this) implements LoggerInterface {
58 | use LoggerTrait;
59 |
60 | private TestCase $test_case;
61 |
62 | public function __construct(TestCase $test_case)
63 | {
64 | $this->test_case = $test_case;
65 | }
66 |
67 | public function log($level, $message, array $context = [])
68 | {
69 | $this->test_case->assertSame('mkdir', $context['method']);
70 | }
71 | }
72 | );
73 |
74 | $sut->getattr('/', new Stat());
75 | $sut->mkdir('/', 0);
76 | }
77 |
78 | /** @dataProvider dataProvider */
79 | public function testLogUnImplemented(string $method, ...$args)
80 | {
81 | $sut = new LogUnimplementedFilesystem(
82 | new NullFilesystem(),
83 | new class ($this, $method) implements LoggerInterface {
84 | use LoggerTrait;
85 |
86 | private TestCase $test_case;
87 | private string $method;
88 |
89 | public function __construct(TestCase $test_case, string $method)
90 | {
91 | $this->test_case = $test_case;
92 | $this->method = $method;
93 | }
94 |
95 | public function log($level, $message, array $context = [])
96 | {
97 | $this->test_case->assertSame($this->method, $context['method']);
98 | }
99 | }
100 | );
101 |
102 | ([$sut, $method])(...$args);
103 | }
104 |
105 | public function dataProvider(): array
106 | {
107 | return [
108 | 'getattr' => ['getattr', '/', new Stat()],
109 | 'readlink' => ['readlink', '/', new CStringBuffer(CStringBuffer::newCData()), 1],
110 | 'getdir' => [
111 | 'getdir',
112 | '/',
113 | new FuseDirHandle(FFI::new(FuseDirHandle::getCTypeName())),
114 | new FuseDirFill(FFI::new('void *')),
115 | ],
116 | 'mknod' => ['mknod', '/', 0, 0],
117 | 'mkdir' => ['mkdir', '/', 0],
118 | 'unlink' => ['unlink', '/'],
119 | 'rmdir' => ['rmdir', '/'],
120 | 'symlink' => ['symlink', 'path', 'link'],
121 | 'rename' => ['rename', '/from', '/to'],
122 | 'link' => ['link', 'path', 'link'],
123 | 'chmod' => ['chmod', '/', 0],
124 | 'chown' => ['chown', '/', 1, 1],
125 | 'truncate' => ['truncate', '/', 0],
126 | 'utime' => ['utime', '/', new UtimBuf()],
127 | 'open' => ['open', '/', new FuseFileInfo()],
128 | 'read' => ['read', '/', new CBytesBuffer(CBytesBuffer::newCData()), 1, 0, new FuseFileInfo()],
129 | 'write' => ['write', '/', 'content', 7, 0, new FuseFileInfo()],
130 | 'statfs' => ['statfs', '/', new StatVfs()],
131 | 'flush' => ['flush', '/', new FuseFileInfo()],
132 | 'release' => ['release', '/', new FuseFileInfo()],
133 | 'fsync' => ['fsync', '/', 0, new FuseFileInfo()],
134 | 'setxattr' => ['setxattr', '/', 'name', 'value', 5],
135 | 'getxattr' => ['getxattr', '/', 'name', '', 5],
136 | 'listxattr' => ['listxattr', '/', '', 0],
137 | 'removexattr' => ['removexattr', '/', 'name'],
138 | 'opendir' => ['opendir', '/', new FuseFileInfo()],
139 | 'readdir' => [
140 | 'readdir',
141 | '/',
142 | new FuseReadDirBuffer(FFI::new('void *')),
143 | new FuseFillDir(FFI::new('void *')),
144 | 0,
145 | new FuseFileInfo()
146 | ],
147 | 'releasedir' => ['releasedir', '/', new FuseFileInfo()],
148 | 'fsyncdir' => ['fsyncdir', '/', new FuseFileInfo()],
149 | 'init' => ['init', new FuseConnInfo()],
150 | 'destroy' => ['destroy', null],
151 | 'access' => ['access', '/', 0],
152 | 'create' => ['create', '/', 0, new FuseFileInfo()],
153 | 'ftruncate' => ['ftruncate', '/', 0, new FuseFileInfo()],
154 | 'fgetattr' => ['fgetattr', '/', new Stat(), new FuseFileInfo()],
155 | 'lock' => ['lock', '/', new FuseFileInfo(), 0, new Flock()],
156 | 'utimens' => [
157 | 'utimens',
158 | '/',
159 | new TypedCDataArray(
160 | FFI::new('void *'),
161 | TimeSpec::class
162 | )
163 | ],
164 | 'bmap' => ['bmap', '/', 0, 0],
165 | 'ioctl' => [
166 | 'ioctl',
167 | '/',
168 | 0,
169 | new FuseIoctlArgPointer(FFI::new('void *')),
170 | new FuseFileInfo(),
171 | 0,
172 | new FuseIoctlDataPointer(FFI::new('void *'))
173 | ],
174 | 'poll' => [
175 | 'poll',
176 | '/',
177 | new FuseFileInfo(),
178 | new FusePollHandle(FFI::new('void *')),
179 | 0
180 | ],
181 | 'writeBuf' => ['writeBuf', '/', new FuseBufVec(), 0, new FuseFileInfo()],
182 | 'readBuf' => [
183 | 'readBuf',
184 | '/',
185 | new TypedCDataArray(
186 | FFI::new('void *'),
187 | FuseBufVec::class
188 | ),
189 | 0,
190 | 0,
191 | new FuseFileInfo()
192 | ],
193 | 'flock' => ['flock', '/', new FuseFileInfo(), 0],
194 | 'fallocate' => ['fallocate', '/', 0, 0, new FuseFileInfo()],
195 | ];
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/tests/Filesystem/ReflectionFilesystemTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse\Filesystem;
15 |
16 | use Fuse\FilesystemDefaultImplementationTrait;
17 | use Fuse\FilesystemInterface;
18 | use Fuse\Libc\Sys\Stat\Stat;
19 | use PHPUnit\Framework\TestCase;
20 |
21 | final class ReflectionFilesystemTest extends TestCase
22 | {
23 | public function testIsDefault()
24 | {
25 | $filesystem = new class implements FilesystemInterface {
26 | use FilesystemDefaultImplementationTrait;
27 |
28 | public function getattr(string $path, Stat $stat): int
29 | {
30 | return 0;
31 | }
32 | };
33 |
34 | $sut = ReflectionFilesystem::instance($filesystem);
35 |
36 | $this->assertFalse($sut->isDefault('getattr'));
37 | $this->assertTrue($sut->isDefault('readlink'));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tools/stubs/FFI/CData.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace FFI;
15 |
16 | class CData
17 | {
18 |
19 | }
20 |
21 | /**
22 | * @implements \ArrayAccess
23 | */
24 | class CDataArray extends CData implements \ArrayAccess
25 | {
26 |
27 | /**
28 | * Whether a offset exists
29 | * @link https://php.net/manual/en/arrayaccess.offsetexists.php
30 | * @param mixed $offset
31 | * An offset to check for.
32 | *
33 | * @return bool true on success or false on failure.
34 | *
35 | *
36 | * The return value will be casted to boolean if non-boolean was returned.
37 | */
38 | public function offsetExists($offset)
39 | {
40 | // TODO: Implement offsetExists() method.
41 | }
42 |
43 | /**
44 | * @param int $offset
45 | */
46 | public function offsetGet($offset): CData
47 | {
48 | // TODO: Implement offsetGet() method.
49 | }
50 |
51 | /**
52 | * Offset to set
53 | * @link https://php.net/manual/en/arrayaccess.offsetset.php
54 | * @param mixed $offset
55 | * The offset to assign the value to.
56 | *
57 | * @param mixed $value
58 | * The value to set.
59 | *
60 | * @return void
61 | */
62 | public function offsetSet($offset, $value)
63 | {
64 | // TODO: Implement offsetSet() method.
65 | }
66 |
67 | /**
68 | * Offset to unset
69 | * @link https://php.net/manual/en/arrayaccess.offsetunset.php
70 | * @param mixed $offset
71 | * The offset to unset.
72 | *
73 | * @return void
74 | */
75 | public function offsetUnset($offset)
76 | {
77 | // TODO: Implement offsetUnset() method.
78 | }
79 | }
--------------------------------------------------------------------------------
/tools/stubs/Fuse/FuseCData.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use FFI\CData;
17 |
18 | class FuseDirFillCData extends CData
19 | {
20 | public function __invoke(CData $dirhandle, string $name, int $type, int $ino): int
21 | {
22 |
23 | }
24 | }
25 |
26 | class FuseFillDirCData extends CData
27 | {
28 | public function __invoke(CData $buf, string $name, ?CData $stbuf, int $off): int
29 | {
30 |
31 | }
32 | }
--------------------------------------------------------------------------------
/tools/stubs/Fuse/FuseFFI.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | namespace Fuse;
15 |
16 | use FFI;
17 | use FFI\CData;
18 |
19 | class FuseFFI extends FFI
20 | {
21 | public function fuse_main_real(int $argc, CData $argv, CData $fuse_operation, int $size, ?CData $user_data): int
22 | {
23 |
24 | }
25 | }
--------------------------------------------------------------------------------