or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-operations.mddata-structures.mdextended-features.mdfile-management.mdindex.md

extended-features.mddocs/

0

# Extended Features

1

2

Advanced FUSE features including extended attributes, file locking, access control, filesystem statistics, and specialized operations for enhanced filesystem functionality.

3

4

## Capabilities

5

6

### Extended Attributes

7

8

Support for extended file attributes (xattrs) that provide additional metadata beyond standard POSIX attributes.

9

10

```python { .api }

11

def getxattr(self, path, name, size):

12

"""

13

Get extended attribute value.

14

15

Args:

16

path (str): Path to file or directory

17

name (str): Attribute name (e.g., 'user.comment')

18

size (int): Maximum size to return (0 = return size needed)

19

20

Returns:

21

bytes: Attribute value

22

int: Size needed (if size=0) or negative errno on error

23

"""

24

25

def setxattr(self, path, name, val, flags):

26

"""

27

Set extended attribute value.

28

29

Args:

30

path (str): Path to file or directory

31

name (str): Attribute name

32

val (bytes): Attribute value

33

flags (int): XATTR_CREATE, XATTR_REPLACE, or 0

34

35

Returns:

36

int: 0 on success, negative errno on error

37

"""

38

39

def listxattr(self, path, size):

40

"""

41

List extended attribute names.

42

43

Args:

44

path (str): Path to file or directory

45

size (int): Maximum size to return (0 = return size needed)

46

47

Returns:

48

bytes: Null-separated attribute names

49

int: Size needed (if size=0) or negative errno on error

50

"""

51

52

def removexattr(self, path, name):

53

"""

54

Remove extended attribute.

55

56

Args:

57

path (str): Path to file or directory

58

name (str): Attribute name to remove

59

60

Returns:

61

int: 0 on success, negative errno on error

62

"""

63

```

64

65

**Usage Example:**

66

67

```python

68

class MyFS(Fuse):

69

def __init__(self, *args, **kwargs):

70

super().__init__(*args, **kwargs)

71

self.xattrs = {} # {path: {name: value}}

72

73

def getxattr(self, path, name, size):

74

if path not in self.xattrs or name not in self.xattrs[path]:

75

return -errno.ENODATA

76

77

value = self.xattrs[path][name]

78

if size == 0:

79

return len(value) # Return size needed

80

81

return value[:size]

82

83

def setxattr(self, path, name, val, flags):

84

if path not in self.files and path not in self.dirs:

85

return -errno.ENOENT

86

87

if path not in self.xattrs:

88

self.xattrs[path] = {}

89

90

exists = name in self.xattrs[path]

91

92

if flags == XATTR_CREATE and exists:

93

return -errno.EEXIST

94

if flags == XATTR_REPLACE and not exists:

95

return -errno.ENODATA

96

97

self.xattrs[path][name] = val

98

return 0

99

100

def listxattr(self, path, size):

101

if path not in self.xattrs:

102

return b''

103

104

names = b'\0'.join(name.encode() for name in self.xattrs[path].keys())

105

if names:

106

names += b'\0' # Null-terminate the list

107

108

if size == 0:

109

return len(names)

110

111

return names[:size]

112

```

113

114

### File Locking

115

116

Advisory file locking operations for coordinating access between processes.

117

118

```python { .api }

119

def lock(self, path, fip, cmd, lock):

120

"""

121

File locking operations.

122

123

Args:

124

path (str): Path to file

125

fip: File info pointer (usually None)

126

cmd (int): Lock command (F_GETLK, F_SETLK, F_SETLKW)

127

lock (Flock): Lock specification

128

129

Returns:

130

int: 0 on success, negative errno on error

131

Flock: Lock information (for F_GETLK)

132

"""

133

```

134

135

**Usage Example:**

136

137

```python

138

import fcntl

139

140

class MyFS(Fuse):

141

def __init__(self, *args, **kwargs):

142

super().__init__(*args, **kwargs)

143

self.locks = {} # {path: [lock_info, ...]}

144

145

def lock(self, path, fip, cmd, lock):

146

if path not in self.files:

147

return -errno.ENOENT

148

149

if cmd == fcntl.F_GETLK:

150

# Check for conflicting locks

151

for existing_lock in self.locks.get(path, []):

152

if self.locks_conflict(lock, existing_lock):

153

return existing_lock

154

155

# No conflict - set type to F_UNLCK

156

result = fuse.Flock()

157

result.l_type = fcntl.F_UNLCK

158

return result

159

160

elif cmd == fcntl.F_SETLK:

161

# Non-blocking lock

162

if self.has_conflicting_lock(path, lock):

163

return -errno.EAGAIN

164

return self.set_lock(path, lock)

165

166

elif cmd == fcntl.F_SETLKW:

167

# Blocking lock (would block in real implementation)

168

return self.set_lock(path, lock)

169

170

def locks_conflict(self, lock1, lock2):

171

# Check if two locks conflict

172

if lock1.l_type == fcntl.F_UNLCK or lock2.l_type == fcntl.F_UNLCK:

173

return False

174

175

if lock1.l_type == fcntl.F_RDLCK and lock2.l_type == fcntl.F_RDLCK:

176

return False # Read locks don't conflict

177

178

# Check range overlap

179

return self.ranges_overlap(lock1, lock2)

180

```

181

182

### Access Control

183

184

Enhanced access permission checking beyond basic POSIX permissions.

185

186

```python { .api }

187

def access(self, path, mode):

188

"""

189

Check file access permissions.

190

191

Args:

192

path (str): Path to file or directory

193

mode (int): Access mode to check (R_OK, W_OK, X_OK, F_OK)

194

195

Returns:

196

int: 0 if access granted, negative errno on error

197

"""

198

```

199

200

**Usage Example:**

201

202

```python

203

import os

204

205

class MyFS(Fuse):

206

def access(self, path, mode):

207

if path not in self.files and path not in self.dirs:

208

return -errno.ENOENT

209

210

# Get current context

211

ctx = self.GetContext()

212

uid = ctx.get('uid', 0)

213

gid = ctx.get('gid', 0)

214

215

# Get file attributes

216

st = self.getattr(path)

217

218

# Check ownership and permissions

219

if uid == 0: # Root can access anything

220

return 0

221

222

# Check user permissions

223

if uid == st.st_uid:

224

user_perms = (st.st_mode >> 6) & 7

225

elif gid == st.st_gid:

226

user_perms = (st.st_mode >> 3) & 7

227

else:

228

user_perms = st.st_mode & 7

229

230

# Check requested access

231

if mode & os.R_OK and not (user_perms & 4):

232

return -errno.EACCES

233

if mode & os.W_OK and not (user_perms & 2):

234

return -errno.EACCES

235

if mode & os.X_OK and not (user_perms & 1):

236

return -errno.EACCES

237

238

return 0

239

```

240

241

### Context Information

242

243

Access information about the current FUSE request context.

244

245

```python { .api }

246

def GetContext(self):

247

"""

248

Get current request context.

249

250

Returns:

251

dict: Context information with keys:

252

- uid: User ID of calling process

253

- gid: Group ID of calling process

254

- pid: Process ID of calling process

255

"""

256

```

257

258

**Usage Example:**

259

260

```python

261

class MyFS(Fuse):

262

def create(self, path, mode, fi):

263

# Get context of calling process

264

ctx = self.GetContext()

265

266

# Set file ownership to calling user

267

st = fuse.Stat()

268

st.st_mode = mode

269

st.st_uid = ctx['uid']

270

st.st_gid = ctx['gid']

271

st.st_size = 0

272

273

# Create file with proper ownership

274

self.files[path] = b''

275

self.file_attrs[path] = st

276

277

return 0

278

```

279

280

### Cache Management

281

282

Control kernel caching behavior for performance optimization.

283

284

```python { .api }

285

def Invalidate(self, path):

286

"""

287

Invalidate cached entry.

288

289

Args:

290

path (str): Path to invalidate in kernel cache

291

292

Returns:

293

int: 0 on success, negative errno on error

294

"""

295

```

296

297

**Usage Example:**

298

299

```python

300

class MyFS(Fuse):

301

def write(self, path, buf, offset):

302

# Update file content

303

result = self.do_write(path, buf, offset)

304

305

# Invalidate cache since file changed

306

if result > 0:

307

self.Invalidate(path)

308

309

return result

310

311

def setxattr(self, path, name, val, flags):

312

result = self.do_setxattr(path, name, val, flags)

313

314

# Invalidate cache for attribute changes

315

if result == 0:

316

self.Invalidate(path)

317

318

return result

319

```

320

321

### I/O Control Operations

322

323

Handle filesystem-specific I/O control operations.

324

325

```python { .api }

326

def ioctl(self, path, cmd, arg, fip, flags, data):

327

"""

328

I/O control operations.

329

330

Args:

331

path (str): Path to file

332

cmd (int): I/O control command

333

arg: Command argument

334

fip: File info pointer

335

flags (int): FUSE I/O control flags

336

data: Input/output data

337

338

Returns:

339

int: 0 on success, negative errno on error

340

bytes: Output data for some operations

341

"""

342

```

343

344

**Usage Example:**

345

346

```python

347

# Define custom ioctl commands

348

MYFS_IOCTL_GET_INFO = 0x1000

349

MYFS_IOCTL_SET_FLAG = 0x1001

350

351

class MyFS(Fuse):

352

def ioctl(self, path, cmd, arg, fip, flags, data):

353

if path not in self.files:

354

return -errno.ENOENT

355

356

if cmd == MYFS_IOCTL_GET_INFO:

357

# Return file information

358

info = {

359

'size': len(self.files[path]),

360

'created': self.file_created[path]

361

}

362

return json.dumps(info).encode()

363

364

elif cmd == MYFS_IOCTL_SET_FLAG:

365

# Set filesystem-specific flag

366

flag_value = struct.unpack('I', data)[0]

367

self.file_flags[path] = flag_value

368

return 0

369

370

else:

371

return -errno.ENOTTY # Inappropriate ioctl

372

```

373

374

### Poll Support

375

376

Support for poll/select operations on files.

377

378

```python { .api }

379

def poll(self, path, fip, ph, reventsp):

380

"""

381

Poll file for events.

382

383

Args:

384

path (str): Path to file

385

fip: File info pointer

386

ph: Poll handle for notifications

387

reventsp: Pointer to returned events

388

389

Returns:

390

int: 0 on success, negative errno on error

391

"""

392

393

def NotifyPoll(self, ph):

394

"""

395

Notify poll completion.

396

397

Args:

398

ph: Poll handle from poll() call

399

"""

400

```

401

402

### Filesystem Lifecycle

403

404

Handle filesystem initialization and cleanup.

405

406

```python { .api }

407

def fsinit(self):

408

"""

409

Initialize filesystem.

410

411

Called when filesystem is mounted.

412

413

Returns:

414

int: 0 on success, negative errno on error

415

"""

416

417

def fsdestroy(self):

418

"""

419

Clean up filesystem.

420

421

Called when filesystem is unmounted.

422

"""

423

```

424

425

**Usage Example:**

426

427

```python

428

class MyFS(Fuse):

429

def fsinit(self):

430

"""Initialize filesystem resources."""

431

print("Filesystem mounting...")

432

433

# Initialize data structures

434

self.files = {}

435

self.dirs = {'/': {}}

436

self.xattrs = {}

437

438

# Load persistent data if needed

439

self.load_filesystem_state()

440

441

return 0

442

443

def fsdestroy(self):

444

"""Clean up filesystem resources."""

445

print("Filesystem unmounting...")

446

447

# Save persistent data

448

self.save_filesystem_state()

449

450

# Clean up resources

451

self.cleanup_resources()

452

```

453

454

## Error Handling

455

456

Extended features may raise specialized exceptions:

457

458

```python { .api }

459

class FuseError(Exception):

460

"""

461

FUSE-specific error.

462

463

Raised by feature checking functions and other FUSE operations

464

when the underlying FUSE library doesn't support a feature or

465

when a FUSE-specific error occurs.

466

"""

467

```

468

469

**Usage Example:**

470

471

```python

472

try:

473

# Check if FUSE library supports extended attributes

474

fuse.feature_assert('has_getxattr', 'has_setxattr')

475

476

# Enable extended attribute support

477

self.supports_xattrs = True

478

479

except fuse.FuseError as e:

480

print(f"Extended attributes not supported: {e}")

481

self.supports_xattrs = False

482

483

def getxattr(self, path, name, size):

484

if not self.supports_xattrs:

485

return -errno.ENOTSUP

486

487

# Implementation here...

488

```

489

490

## Best Practices

491

492

- Implement extended attributes for applications that rely on them

493

- Use file locking for multi-process coordination when needed

494

- Implement proper access control based on process context

495

- Use cache invalidation judiciously to balance performance and consistency

496

- Handle ioctl operations for filesystem-specific functionality

497

- Provide meaningful poll support for applications that need it

498

- Initialize and clean up resources properly in fsinit/fsdestroy

499

- Test extended features with real applications that use them

500

- Use feature checking functions to verify FUSE library capabilities

501

- Handle FuseError exceptions gracefully for unsupported features