or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-classes.mdexception-handling.mdindex.mdutilities.md

core-classes.mddocs/

0

# Core Classes

1

2

The primary classes that form the foundation of mfusepy's filesystem interface. These provide the essential framework for creating and mounting custom filesystems in Python.

3

4

## Capabilities

5

6

### FUSE Class

7

8

The main interface class that manages the FUSE mount process, handles callback translation between Python and the native FUSE library, and provides mount configuration options.

9

10

```python { .api }

11

class FUSE:

12

"""Lower level interface for FUSE filesystem implementation."""

13

14

OPTIONS = (

15

('foreground', '-f'),

16

('debug', '-d'),

17

('nothreads', '-s'),

18

)

19

20

def __init__(self, operations, mountpoint: str, raw_fi: bool = False,

21

encoding: str = 'utf-8', **kwargs) -> None:

22

"""

23

Mount a FUSE filesystem.

24

25

Args:

26

operations: Instance of Operations subclass implementing filesystem behavior

27

mountpoint: Directory path where filesystem will be mounted

28

raw_fi: If True, pass raw fuse_file_info structures to operations

29

encoding: Character encoding for path/name conversions (default: 'utf-8')

30

**kwargs: Additional FUSE mount options (foreground, debug, nothreads, etc.)

31

"""

32

```

33

34

#### Usage Example

35

36

```python

37

from mfusepy import FUSE, Operations

38

39

class MyFS(Operations):

40

def getattr(self, path, fh=None):

41

# Implement filesystem operations

42

pass

43

44

# Mount with default options

45

filesystem = MyFS()

46

fuse = FUSE(filesystem, '/mnt/myfs')

47

48

# Mount with custom options

49

fuse = FUSE(filesystem, '/mnt/myfs',

50

foreground=True, debug=True,

51

allow_other=True, raw_fi=True)

52

```

53

54

### Operations Base Class

55

56

Abstract base class that defines the interface for filesystem operations. Subclass this to implement custom filesystem behavior by overriding the methods corresponding to the filesystem operations you want to support.

57

58

```python { .api }

59

class Operations:

60

"""Base class to be subclassed for FUSE filesystem operations."""

61

62

# File and Directory Operations

63

def getattr(self, path: str, fh: Optional[int] = None) -> dict[str, Any]:

64

"""

65

Get file attributes (like stat()).

66

67

Args:

68

path: File path

69

fh: File handle (optional)

70

71

Returns:

72

Dictionary with stat-like attributes:

73

- st_mode: File mode (permissions + type)

74

- st_nlink: Number of hard links

75

- st_size: File size in bytes

76

- st_uid: User ID of owner

77

- st_gid: Group ID of owner

78

- st_atime: Access time

79

- st_mtime: Modification time

80

- st_ctime: Change time

81

"""

82

83

def readdir(self, path: str, fh: int) -> ReadDirResult:

84

"""

85

Read directory contents.

86

87

Args:

88

path: Directory path

89

fh: Directory file handle

90

91

Returns:

92

Iterable of directory entries. Each entry can be:

93

- str: Just the filename

94

- tuple[str, dict[str, int], int]: (name, stat_dict, offset)

95

- tuple[str, int, int]: (name, ino, offset)

96

"""

97

98

def readlink(self, path: str) -> str:

99

"""Read the target of a symbolic link."""

100

101

def mknod(self, path: str, mode: int, dev: int) -> int:

102

"""Create a file node (regular file, device special, or named pipe)."""

103

104

def mkdir(self, path: str, mode: int) -> int:

105

"""Create a directory."""

106

107

def unlink(self, path: str) -> int:

108

"""Remove a file."""

109

110

def rmdir(self, path: str) -> int:

111

"""Remove a directory."""

112

113

def symlink(self, target: str, source: str) -> int:

114

"""Create a symbolic link."""

115

116

def rename(self, old: str, new: str) -> int:

117

"""Rename a file or directory."""

118

119

def link(self, target: str, source: str) -> int:

120

"""Create a hard link."""

121

122

def chmod(self, path: str, mode: int) -> int:

123

"""Change file permissions."""

124

125

def chown(self, path: str, uid: int, gid: int) -> int:

126

"""Change file ownership."""

127

128

def truncate(self, path: str, length: int, fh: Optional[int] = None) -> int:

129

"""Truncate a file to a specified length."""

130

131

def utimens(self, path: str, times: Optional[tuple[int, int]] = None) -> int:

132

"""Update file timestamps."""

133

134

# File I/O Operations

135

def open(self, path: str, flags: int) -> int:

136

"""

137

Open a file.

138

139

Args:

140

path: File path

141

flags: Open flags (O_RDONLY, O_WRONLY, O_RDWR, etc.)

142

143

Returns:

144

File handle (integer)

145

"""

146

147

def read(self, path: str, size: int, offset: int, fh: int) -> bytes:

148

"""

149

Read data from a file.

150

151

Args:

152

path: File path

153

size: Number of bytes to read

154

offset: Offset in file to start reading

155

fh: File handle

156

157

Returns:

158

Bytes read from file

159

"""

160

161

def write(self, path: str, data, offset: int, fh: int) -> int:

162

"""

163

Write data to a file.

164

165

Args:

166

path: File path

167

data: Data to write (bytes)

168

offset: Offset in file to start writing

169

fh: File handle

170

171

Returns:

172

Number of bytes written

173

"""

174

175

def flush(self, path: str, fh: int) -> int:

176

"""Flush cached data to storage."""

177

178

def release(self, path: str, fh: int) -> int:

179

"""Release/close an open file."""

180

181

def fsync(self, path: str, datasync: int, fh: int) -> int:

182

"""Synchronize file contents."""

183

184

def create(self, path: str, mode: int, fi=None) -> int:

185

"""Create and open a new file atomically."""

186

187

# Directory Operations

188

def opendir(self, path: str) -> int:

189

"""Open a directory for reading."""

190

191

def releasedir(self, path: str, fh: int) -> int:

192

"""Release/close an open directory."""

193

194

def fsyncdir(self, path: str, datasync: int, fh: int) -> int:

195

"""Synchronize directory contents."""

196

197

# Extended Attributes

198

def setxattr(self, path: str, name: str, value: bytes, options, position=0) -> int:

199

"""Set an extended attribute."""

200

201

def getxattr(self, path: str, name: str, position=0) -> bytes:

202

"""Get an extended attribute."""

203

204

def listxattr(self, path: str) -> Iterable[str]:

205

"""List extended attributes."""

206

207

def removexattr(self, path: str, name: str) -> int:

208

"""Remove an extended attribute."""

209

210

# File System Operations

211

def statfs(self, path: str) -> dict[str, int]:

212

"""

213

Get filesystem statistics.

214

215

Returns:

216

Dictionary with filesystem statistics:

217

- f_bsize: Block size

218

- f_frsize: Fragment size

219

- f_blocks: Total blocks

220

- f_bfree: Free blocks

221

- f_bavail: Available blocks

222

- f_files: Total inodes

223

- f_ffree: Free inodes

224

- f_favail: Available inodes

225

"""

226

227

def access(self, path: str, amode: int) -> int:

228

"""Check file access permissions."""

229

230

# Lifecycle Operations

231

def init(self, path: str) -> None:

232

"""Initialize filesystem (called after mount)."""

233

234

def init_with_config(self, conn_info: Optional['fuse_conn_info'],

235

config_3: Optional['fuse_config']) -> None:

236

"""Initialize filesystem with FUSE 3.x configuration."""

237

238

def destroy(self, path: str) -> None:

239

"""Cleanup on unmount."""

240

241

# Advanced Operations

242

def bmap(self, path: str, blocksize: int, idx) -> int:

243

"""Map file block to device block."""

244

245

def ioctl(self, path: str, cmd: int, arg, fh: int, flags: int, data) -> int:

246

"""Device-specific I/O control."""

247

248

def lock(self, path: str, fh: int, cmd: int, lock) -> int:

249

"""POSIX file locking."""

250

251

def poll(self, path: str, fh: int, ph, reventsp) -> int:

252

"""Poll for I/O events."""

253

254

def write_buf(self, path: str, buf, offset: int, fh: int) -> int:

255

"""Write using buffer (FUSE 3.x optimization)."""

256

257

def read_buf(self, path: str, bufpp, size: int, offset: int, fh: int) -> int:

258

"""Read into buffer (FUSE 3.x optimization)."""

259

260

def flock(self, path: str, fh: int, op: int) -> int:

261

"""BSD file locking."""

262

263

def fallocate(self, path: str, mode: int, offset: int, size: int, fh: int) -> int:

264

"""Allocate file space."""

265

266

def copy_file_range(self, path_in: str, fh_in: int, offset_in: int,

267

path_out: str, fh_out: int, offset_out: int,

268

length: int, flags: int) -> int:

269

"""

270

Copy a range of data from one file to another (FUSE 3.x).

271

272

Args:

273

path_in: Source file path

274

fh_in: Source file handle

275

offset_in: Offset in source file

276

path_out: Destination file path

277

fh_out: Destination file handle

278

offset_out: Offset in destination file

279

length: Number of bytes to copy

280

flags: Copy operation flags

281

282

Returns:

283

Number of bytes copied

284

"""

285

286

def lseek(self, path: str, offset: int, whence: int, fh: int) -> int:

287

"""

288

Seek to a position in a file (FUSE 3.x).

289

290

Args:

291

path: File path

292

offset: Byte offset to seek to

293

whence: How to interpret offset (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END)

294

fh: File handle

295

296

Returns:

297

New file position (absolute offset from beginning)

298

"""

299

```

300

301

#### FUSE 3.x Operations Example

302

303

```python

304

class ModernFS(Operations):

305

def copy_file_range(self, path_in, fh_in, offset_in,

306

path_out, fh_out, offset_out, length, flags):

307

"""Efficient file copying using copy_file_range."""

308

try:

309

# Read from source file

310

data = self._read_file_data(path_in, length, offset_in)

311

# Write to destination file

312

written = self._write_file_data(path_out, data, offset_out)

313

return written

314

except IOError:

315

raise FuseOSError(errno.EIO)

316

317

def lseek(self, path, offset, whence, fh):

318

"""Seek within a file."""

319

try:

320

file_obj = self.open_files[fh]

321

if whence == os.SEEK_SET:

322

new_pos = offset

323

elif whence == os.SEEK_CUR:

324

new_pos = file_obj.tell() + offset

325

elif whence == os.SEEK_END:

326

file_size = self._get_file_size(path)

327

new_pos = file_size + offset

328

else:

329

raise FuseOSError(errno.EINVAL)

330

331

return new_pos

332

except (KeyError, IOError):

333

raise FuseOSError(errno.EBADF)

334

```

335

336

#### Implementation Example

337

338

```python

339

import os

340

import errno

341

from mfusepy import Operations, FuseOSError

342

343

class PassthroughFS(Operations):

344

"""A passthrough filesystem that mirrors another directory."""

345

346

def __init__(self, root):

347

self.root = root

348

349

def _full_path(self, partial):

350

if partial.startswith("/"):

351

partial = partial[1:]

352

path = os.path.join(self.root, partial)

353

return path

354

355

def getattr(self, path, fh=None):

356

full_path = self._full_path(path)

357

try:

358

st = os.lstat(full_path)

359

return {

360

'st_mode': st.st_mode,

361

'st_nlink': st.st_nlink,

362

'st_size': st.st_size,

363

'st_uid': st.st_uid,

364

'st_gid': st.st_gid,

365

'st_atime': st.st_atime,

366

'st_mtime': st.st_mtime,

367

'st_ctime': st.st_ctime,

368

}

369

except OSError as e:

370

raise FuseOSError(e.errno)

371

372

def readdir(self, path, fh):

373

full_path = self._full_path(path)

374

try:

375

dirents = ['.', '..']

376

dirents.extend(os.listdir(full_path))

377

return dirents

378

except OSError as e:

379

raise FuseOSError(e.errno)

380

381

def read(self, path, length, offset, fh):

382

full_path = self._full_path(path)

383

try:

384

with open(full_path, 'rb') as f:

385

f.seek(offset)

386

return f.read(length)

387

except OSError as e:

388

raise FuseOSError(e.errno)

389

```

390

391

## C Structure Classes

392

393

These classes represent the C structures used by the FUSE library. They are primarily used internally but may be exposed when using raw_fi=True mode.

394

395

```python { .api }

396

class c_timespec(ctypes.Structure):

397

"""Time specification structure."""

398

399

class c_utimbuf(ctypes.Structure):

400

"""Time buffer structure for file timestamps."""

401

402

class c_stat(ctypes.Structure):

403

"""File status structure."""

404

405

class c_statvfs(ctypes.Structure):

406

"""File system statistics structure."""

407

408

class fuse_file_info(ctypes.Structure):

409

"""FUSE file information structure."""

410

411

class fuse_context(ctypes.Structure):

412

"""FUSE context information structure."""

413

414

class fuse_conn_info(ctypes.Structure):

415

"""FUSE connection information structure."""

416

417

class fuse_config(ctypes.Structure):

418

"""FUSE configuration structure."""

419

420

class fuse_buf(ctypes.Structure):

421

"""FUSE buffer structure."""

422

423

class fuse_bufvec(ctypes.Structure):

424

"""FUSE buffer vector structure."""

425

426

class fuse_operations(ctypes.Structure):

427

"""FUSE operations structure."""

428

429

class c_flock_t(ctypes.Structure):

430

"""File locking structure (platform-specific)."""

431

```

432

433

## Type Definitions

434

435

```python { .api }

436

from typing import Union, Iterable

437

import ctypes

438

439

FieldsEntry = Union[tuple[str, type], tuple[str, type, int]]

440

ReadDirResult = Iterable[Union[str, tuple[str, dict[str, int], int], tuple[str, int, int]]]

441

FuseConfigPointer = ctypes.POINTER(fuse_config)

442

FuseConnInfoPointer = ctypes.POINTER(fuse_conn_info)

443

```