Skip to content

Commit 63f7a31

Browse files
authored
Merge pull request #1 from sj-i/add_new_api
Add OO api
2 parents c50db1e + 524bfb6 commit 63f7a31

11 files changed

+1797
-25
lines changed

example/array_fs.php

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the sj-i/php-fuse package.
5+
*
6+
* (c) sji <sji@sj-i.dev>
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 FFI\CData;
15+
use Fuse\FilesystemDefaultImplementationTrait;
16+
use Fuse\FilesystemInterface;
17+
use Fuse\Fuse;
18+
use Fuse\Mounter;
19+
20+
require 'vendor/autoload.php';
21+
22+
const ENOENT = 2;
23+
const S_IFDIR = 0040000;
24+
const S_IFREG = 0100000;
25+
26+
class ArrayFs implements FilesystemInterface
27+
{
28+
use FilesystemDefaultImplementationTrait;
29+
30+
private array $array;
31+
32+
public function __construct(array $array)
33+
{
34+
$this->array = $array;
35+
}
36+
37+
public function getArray(): array
38+
{
39+
return $this->array;
40+
}
41+
42+
public function getattr(string $path, \FFI\CData $stbuf): int
43+
{
44+
$typename = 'struct stat';
45+
$type = Fuse::getInstance()->ffi->type(
46+
$typename
47+
);
48+
$size = FFI::sizeof(
49+
$type
50+
);
51+
echo "attr read {$path}" . PHP_EOL;
52+
53+
FFI::memset($stbuf, 0, $size);
54+
if ($path === '/') {
55+
$stbuf->st_mode = S_IFDIR | 0777;
56+
$stbuf->st_nlink = 2;
57+
$stbuf->st_uid = getmyuid();
58+
$stbuf->st_gid = getmygid();
59+
return 0;
60+
}
61+
62+
$element = $this->getEntry($path);
63+
if (is_null($element)) {
64+
return -ENOENT;
65+
}
66+
if (is_array($element)) {
67+
$stbuf->st_mode = S_IFDIR | 0777;
68+
$stbuf->st_nlink = 2;
69+
$stbuf->st_uid = getmyuid();
70+
$stbuf->st_gid = getmygid();
71+
return 0;
72+
}
73+
$stbuf->st_mode = S_IFREG | 0777;
74+
$stbuf->st_nlink = 1;
75+
$stbuf->st_size = strlen((string)$element);
76+
$stbuf->st_uid = getmyuid();
77+
$stbuf->st_gid = getmygid();
78+
return 0;
79+
}
80+
81+
private function &getRecursive(&$array, array $offsets, ?callable $operation = null)
82+
{
83+
$null = null;
84+
85+
$count = count($offsets);
86+
87+
if ($count === 0) {
88+
return $null;
89+
}
90+
if ($count === 1) {
91+
if (isset($array[$offsets[0]])) {
92+
if (!is_null($operation)) {
93+
return $operation($array, $offsets[0]);
94+
} else {
95+
return $array[$offsets[0]];
96+
}
97+
} else {
98+
return $null;
99+
}
100+
}
101+
102+
$offset = array_shift($offsets);
103+
if (is_array($array[$offset])) {
104+
return $this->getRecursive($array[$offset], $offsets);
105+
} else {
106+
return $null;
107+
}
108+
}
109+
110+
/**
111+
* @param string $path
112+
* @return string|array|null
113+
*/
114+
private function &getEntry(string $path)
115+
{
116+
$splitted = explode('/', $path);
117+
array_shift($splitted);
118+
return $this->getRecursive($this->array, $splitted);
119+
}
120+
121+
/**
122+
* @param string $path
123+
* @return string|array|null
124+
*/
125+
private function &getParentEntry(string $path)
126+
{
127+
$splitted = explode('/', $path);
128+
array_shift($splitted);
129+
array_pop($splitted);
130+
if (count($splitted) === 0) {
131+
return $this->array;
132+
}
133+
return $this->getRecursive($this->array, $splitted);
134+
}
135+
136+
/**
137+
* @param string $path
138+
*/
139+
private function unsetEntry(string $path): void
140+
{
141+
$splitted = explode('/', $path);
142+
array_shift($splitted);
143+
$this->getRecursive($this->array, $splitted, function &(array &$array, $index) {
144+
$null = null;
145+
unset($array[$index]);
146+
return $null;
147+
});
148+
}
149+
150+
public function readdir(string $path, CData $buf, CData $filler, int $offset, CData $fi): int
151+
{
152+
$filler($buf, '.', null, 0);
153+
$filler($buf, '..', null, 0);
154+
foreach ($this->array as $key => $value) {
155+
$filler($buf, (string)$key, null, 0);
156+
}
157+
158+
return 0;
159+
}
160+
161+
public function open(string $path, CData $fi): int
162+
{
163+
$entry = $this->getEntry($path);
164+
if (!is_string($entry)) {
165+
return -ENOENT;
166+
}
167+
168+
echo "open {$path}" . PHP_EOL;
169+
return 0;
170+
}
171+
172+
public function read(string $path, CData $buf, int $size, int $offset, CData $fi): int
173+
{
174+
$entry = $this->getEntry($path);
175+
176+
echo "read {$path}" . PHP_EOL;
177+
178+
$len = strlen($entry);
179+
180+
if ($offset + $size > $len) {
181+
$size = ($len - $offset);
182+
}
183+
184+
$content = substr($entry, $offset, $size);
185+
FFI::memcpy($buf, $content, $size);
186+
187+
return $size;
188+
}
189+
190+
public function write(string $path, string $buffer, int $size, int $offset, CData $fuse_file_info): int
191+
{
192+
$entry = &$this->getEntry($path);
193+
$entry = substr_replace($entry, $buffer, $offset, $size);
194+
195+
return $size;
196+
}
197+
198+
public function create(string $path, int $mode, CData $fuse_file_info): int
199+
{
200+
$entry = &$this->getParentEntry($path);
201+
if (is_array($entry)) {
202+
$segments = explode('/', $path);
203+
$filename = array_pop($segments);
204+
$entry[$filename] = '';
205+
return 0;
206+
} else {
207+
return ENOENT;
208+
}
209+
}
210+
211+
public function unlink(string $path): int
212+
{
213+
$this->unsetEntry($path);
214+
return 0;
215+
}
216+
217+
public function rename(string $from, string $to): int
218+
{
219+
$fromValue = $this->getEntry($from);
220+
$parent_entry = &$this->getParentEntry($to);
221+
if (is_array($parent_entry)) {
222+
$segments = explode('/', $to);
223+
$filename = array_pop($segments);
224+
$parent_entry[$filename] = $fromValue;
225+
$this->unsetEntry($from);
226+
return 0;
227+
} else {
228+
return ENOENT;
229+
}
230+
}
231+
}
232+
233+
234+
$mounter = new Mounter();
235+
$array_fs = new ArrayFs([
236+
1,
237+
2,
238+
'foo' => 'bar',
239+
]);
240+
$result = $mounter->mount('/tmp/example/', $array_fs);
241+
var_dump($array_fs->getArray());
242+
return $result;

example/dummy_file.php

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use FFI\CData;
66
use Fuse\Fuse;
7+
use Fuse\FuseOperations;
8+
use Fuse\Mounter;
79

810
const FILE_PATH = '/example';
911
const FILE_NAME = 'example';
@@ -80,16 +82,11 @@ function read_cb(string $path, CData $buf, int $size, int $offset, CData $fi)
8082
return $size;
8183
}
8284

85+
$fuse_operations = new FuseOperations();
86+
$fuse_operations->getattr = 'getattr_cb';
87+
$fuse_operations->open = 'open_cb';
88+
$fuse_operations->read = 'read_cb';
89+
$fuse_operations->readdir = 'readdir_cb';
8390

84-
$fuse_my_operations = Fuse::getInstance()->ffi->new('struct fuse_operations');
85-
$fuse_my_operations->getattr = Closure::fromCallable('getattr_cb');
86-
$fuse_my_operations->open = Closure::fromCallable('open_cb');
87-
$fuse_my_operations->read = Closure::fromCallable('read_cb');
88-
$fuse_my_operations->readdir = Closure::fromCallable('readdir_cb');
89-
90-
return Fuse::getInstance()->main(
91-
$argc,
92-
$argv,
93-
$fuse_my_operations,
94-
null
95-
);
91+
$mounter = new Mounter();
92+
return $mounter->mount('/tmp/example/', $fuse_operations);

example/dummy_file_oo.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
include __DIR__ . "/../vendor/autoload.php";
4+
5+
use FFI\CData;
6+
use Fuse\FilesystemDefaultImplementationTrait;
7+
use Fuse\FilesystemInterface;
8+
use Fuse\Fuse;
9+
use Fuse\Mounter;
10+
11+
const FILE_PATH = '/example';
12+
const FILE_NAME = 'example';
13+
const FILE_CONTENT = 'hello FUSE from PHP' . PHP_EOL;
14+
15+
const ENOENT = 2;
16+
const S_IFDIR = 0040000;
17+
const S_IFREG = 0100000;
18+
19+
class DummyFs implements FilesystemInterface
20+
{
21+
use FilesystemDefaultImplementationTrait;
22+
23+
public function getattr(string $path, \FFI\CData $stbuf): int
24+
{
25+
$typename = 'struct stat';
26+
$type = Fuse::getInstance()->ffi->type(
27+
$typename
28+
);
29+
$size = FFI::sizeof(
30+
$type
31+
);
32+
echo "attr read {$path}" . PHP_EOL;
33+
34+
FFI::memset($stbuf, 0, $size);
35+
if ($path === '/') {
36+
$stbuf->st_mode = S_IFDIR | 0755;
37+
$stbuf->st_nlink = 2;
38+
$stbuf->st_uid = getmyuid();
39+
$stbuf->st_gid = getmygid();
40+
return 0;
41+
}
42+
43+
if ($path === FILE_PATH) {
44+
$stbuf->st_mode = S_IFREG | 0777;
45+
$stbuf->st_nlink = 1;
46+
$stbuf->st_size = strlen(FILE_CONTENT);
47+
$stbuf->st_uid = getmyuid();
48+
$stbuf->st_gid = getmygid();
49+
return 0;
50+
}
51+
52+
return -ENOENT;
53+
}
54+
55+
public function readdir(string $path, CData $buf, CData $filler, int $offset, CData $fi): int
56+
{
57+
$filler($buf, '.', null, 0);
58+
$filler($buf, '..', null, 0);
59+
$filler($buf, FILE_NAME, null, 0);
60+
61+
return 0;
62+
}
63+
64+
public function open(string $path, CData $fi): int
65+
{
66+
if ($path !== FILE_PATH) {
67+
return -ENOENT;
68+
}
69+
70+
echo "open {$path}" . PHP_EOL;
71+
return 0;
72+
}
73+
74+
public function read(string $path, CData $buf, int $size, int $offset, CData $fi): int
75+
{
76+
echo "read {$path}" . PHP_EOL;
77+
78+
$len = strlen(FILE_CONTENT);
79+
80+
if ($offset + $size > $len) {
81+
$size = ($len - $offset);
82+
}
83+
84+
$content = substr(FILE_CONTENT, $offset, $size);
85+
FFI::memcpy($buf, $content, $size);
86+
87+
return $size;
88+
}
89+
}
90+
91+
$mounter = new Mounter();
92+
return $mounter->mount('/tmp/example/', new DummyFs());

0 commit comments

Comments
 (0)