or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

addressing.mdcapabilities.mddatagram-sockets.mdexceptions.mdfile-descriptors.mdindex.mdnio-channels.mdrmi.mdsocket-pairs.mdunix-sockets.mdutilities.md

file-descriptors.mddocs/

0

# File Descriptor Operations

1

2

Advanced Unix Domain Socket features including file descriptor passing, peer credentials, and ancillary message handling for sophisticated inter-process communication scenarios.

3

4

## Core Imports

5

6

```java

7

import java.io.*;

8

import java.net.*;

9

import org.newsclub.net.unix.AFUNIXSocket;

10

import org.newsclub.net.unix.AFUNIXSocketChannel;

11

import org.newsclub.net.unix.AFUNIXSocketCredentials;

12

import org.newsclub.net.unix.AFUNIXSocketExtensions;

13

import org.newsclub.net.unix.AFSocketCapability;

14

import org.newsclub.net.unix.FileDescriptorAccess;

15

```

16

17

## Capabilities

18

19

### AFUNIXSocketExtensions

20

21

Interface defining advanced Unix Domain Socket extensions beyond the standard Socket API, including file descriptor passing and credential access.

22

23

```java { .api }

24

/**

25

* Advanced Unix Domain Socket extensions interface

26

*/

27

public interface AFUNIXSocketExtensions {

28

29

/**

30

* Gets file descriptors received via ancillary messages

31

* File descriptors are received automatically with regular data

32

* @return Array of received file descriptors, never null

33

* @throws IOException if retrieval fails

34

*/

35

FileDescriptor[] getReceivedFileDescriptors() throws IOException;

36

37

/**

38

* Clears the queue of received file descriptors

39

* Should be called after processing received file descriptors

40

*/

41

void clearReceivedFileDescriptors();

42

43

/**

44

* Sets file descriptors to be sent via ancillary messages

45

* File descriptors will be sent with the next write operation

46

* @param fds File descriptors to send (can be empty to clear)

47

* @throws IOException if setting fails

48

*/

49

void setOutboundFileDescriptors(FileDescriptor... fds) throws IOException;

50

51

/**

52

* Checks if outbound file descriptors are pending

53

* @return true if file descriptors are queued for sending

54

*/

55

boolean hasOutboundFileDescriptors();

56

57

/**

58

* Gets credentials of the peer process

59

* @return Peer credentials information

60

* @throws IOException if retrieval fails or not supported

61

*/

62

AFUNIXSocketCredentials getPeerCredentials() throws IOException;

63

}

64

```

65

66

**Usage Examples:**

67

68

```java

69

import java.io.*;

70

import java.nio.charset.StandardCharsets;

71

import org.newsclub.net.unix.*;

72

73

// Server: Receiving file descriptors

74

File serverSocket = new File("/tmp/fd-server.sock");

75

try (AFUNIXServerSocket server = AFUNIXServerSocket.bindOn(AFUNIXSocketAddress.of(serverSocket))) {

76

System.out.println("Server waiting for connections...");

77

78

try (AFUNIXSocket clientSocket = server.accept()) {

79

System.out.println("Client connected");

80

81

// Read regular data and file descriptors

82

InputStream is = clientSocket.getInputStream();

83

byte[] buffer = new byte[1024];

84

int bytesRead = is.read(buffer);

85

String message = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);

86

System.out.println("Received message: " + message);

87

88

// Check for received file descriptors

89

FileDescriptor[] receivedFds = clientSocket.getReceivedFileDescriptors();

90

System.out.println("Received " + receivedFds.length + " file descriptors");

91

92

for (int i = 0; i < receivedFds.length; i++) {

93

// Use the received file descriptor

94

try (FileInputStream fis = new FileInputStream(receivedFds[i])) {

95

byte[] fileBuffer = new byte[1024];

96

int fileBytes = fis.read(fileBuffer);

97

String fileContent = new String(fileBuffer, 0, fileBytes, StandardCharsets.UTF_8);

98

System.out.println("Content from FD " + i + ": " + fileContent);

99

}

100

}

101

102

// Clear received file descriptors after processing

103

clientSocket.clearReceivedFileDescriptors();

104

105

// Get peer credentials

106

AFUNIXSocketCredentials peerCreds = clientSocket.getPeerCredentials();

107

System.out.println("Peer process ID: " + peerCreds.getPid());

108

System.out.println("Peer user ID: " + peerCreds.getUid());

109

System.out.println("Peer group ID: " + peerCreds.getGid());

110

}

111

}

112

113

// Client: Sending file descriptors

114

File clientSocket = new File("/tmp/fd-client.sock");

115

try (AFUNIXSocket socket = AFUNIXSocket.connectTo(AFUNIXSocketAddress.of(serverSocket))) {

116

117

// Create a temporary file to send

118

File tempFile = File.createTempFile("test", ".txt");

119

try (FileWriter writer = new FileWriter(tempFile)) {

120

writer.write("Hello from shared file!");

121

}

122

123

// Open file descriptor to send

124

FileInputStream fileInput = new FileInputStream(tempFile);

125

FileDescriptor fd = fileInput.getFD();

126

127

// Set file descriptor to be sent

128

socket.setOutboundFileDescriptors(fd);

129

130

// Send regular data (file descriptor will be sent automatically)

131

OutputStream os = socket.getOutputStream();

132

os.write("Sending file descriptor".getBytes(StandardCharsets.UTF_8));

133

os.flush();

134

135

System.out.println("File descriptor sent with message");

136

137

// Clean up

138

fileInput.close();

139

tempFile.delete();

140

}

141

```

142

143

### AFUNIXSocketCredentials

144

145

Container for Unix Domain Socket peer credentials, providing access to peer process information for authentication and authorization.

146

147

```java { .api }

148

/**

149

* Unix Domain Socket peer credentials

150

*/

151

public final class AFUNIXSocketCredentials {

152

153

/**

154

* Gets the process ID of the peer

155

* @return Process ID (PID)

156

*/

157

public long getPid();

158

159

/**

160

* Gets the user ID of the peer process

161

* @return User ID (UID)

162

*/

163

public long getUid();

164

165

/**

166

* Gets the primary group ID of the peer process

167

* @return Primary group ID (GID)

168

*/

169

public long getGid();

170

171

/**

172

* Gets all group IDs of the peer process

173

* @return Array of all group IDs

174

*/

175

public long[] getGids();

176

177

/**

178

* Gets the UUID of the peer process (if available)

179

* @return Process UUID or null

180

*/

181

public String getUUID();

182

183

/**

184

* Creates credentials for the current process

185

* @return Current process credentials

186

*/

187

public static AFUNIXSocketCredentials current();

188

189

/**

190

* Gets remote peer credentials from RMI context

191

* Used in RMI scenarios to identify the calling process

192

* @return Remote peer credentials or null

193

*/

194

public static AFUNIXSocketCredentials remotePeerCredentials();

195

196

/**

197

* String representation of credentials

198

* @return Human-readable credential information

199

*/

200

public String toString();

201

}

202

```

203

204

**Usage Examples:**

205

206

```java

207

import org.newsclub.net.unix.*;

208

209

// Authentication server using peer credentials

210

File authServerSocket = new File("/tmp/auth-server.sock");

211

try (AFUNIXServerSocket server = AFUNIXServerSocket.bindOn(AFUNIXSocketAddress.of(authServerSocket))) {

212

213

while (true) {

214

try (AFUNIXSocket client = server.accept()) {

215

// Get peer credentials for authentication

216

AFUNIXSocketCredentials peerCreds = client.getPeerCredentials();

217

218

System.out.println("Connection from:");

219

System.out.println(" PID: " + peerCreds.getPid());

220

System.out.println(" UID: " + peerCreds.getUid());

221

System.out.println(" GID: " + peerCreds.getGid());

222

223

// Simple authorization check

224

if (peerCreds.getUid() == 0) {

225

System.out.println("Root user detected - full access granted");

226

client.getOutputStream().write("ADMIN_ACCESS".getBytes());

227

} else if (peerCreds.getUid() == getCurrentUserId()) {

228

System.out.println("Same user - standard access granted");

229

client.getOutputStream().write("USER_ACCESS".getBytes());

230

} else {

231

System.out.println("Different user - access denied");

232

client.getOutputStream().write("ACCESS_DENIED".getBytes());

233

}

234

235

client.getOutputStream().flush();

236

}

237

}

238

}

239

240

// Check group memberships

241

AFUNIXSocketCredentials currentCreds = AFUNIXSocketCredentials.current();

242

long[] groups = currentCreds.getGids();

243

System.out.println("Current process belongs to " + groups.length + " groups:");

244

for (long gid : groups) {

245

System.out.println(" GID: " + gid);

246

}

247

```

248

249

### FileDescriptorAccess

250

251

Utility class for advanced file descriptor operations and access to native file descriptor values.

252

253

```java { .api }

254

/**

255

* Utility class for file descriptor access and operations

256

*/

257

public final class FileDescriptorAccess {

258

259

/**

260

* Gets the native file descriptor value from a FileDescriptor

261

* @param fd The FileDescriptor instance

262

* @return Native file descriptor number

263

* @throws IOException if access fails

264

*/

265

public static int getFileDescriptor(FileDescriptor fd) throws IOException;

266

267

/**

268

* Gets the file descriptor from an AFSocket

269

* @param socket The socket instance

270

* @return Socket's file descriptor

271

* @throws IOException if access fails

272

*/

273

public static FileDescriptor getFileDescriptor(AFSocket socket) throws IOException;

274

275

/**

276

* Checks if a file descriptor is valid

277

* @param fd The FileDescriptor to check

278

* @return true if the file descriptor is valid

279

*/

280

public static boolean isValid(FileDescriptor fd);

281

282

/**

283

* Creates a FileDescriptor from a native file descriptor number

284

* @param fdNum Native file descriptor number

285

* @return FileDescriptor instance

286

* @throws IOException if creation fails

287

*/

288

public static FileDescriptor fromNative(int fdNum) throws IOException;

289

}

290

```

291

292

**Usage Examples:**

293

294

```java

295

import org.newsclub.net.unix.*;

296

297

// File descriptor introspection

298

try (AFUNIXSocket socket = AFUNIXSocket.newInstance()) {

299

socket.connect(AFUNIXSocketAddress.of(new File("/tmp/test.sock")));

300

301

// Get the socket's file descriptor

302

FileDescriptor socketFd = FileDescriptorAccess.getFileDescriptor(socket);

303

int nativeFd = FileDescriptorAccess.getFileDescriptor(socketFd);

304

305

System.out.println("Socket file descriptor: " + nativeFd);

306

System.out.println("File descriptor valid: " + FileDescriptorAccess.isValid(socketFd));

307

308

// Create file descriptor for stdout

309

FileDescriptor stdoutFd = FileDescriptorAccess.fromNative(1);

310

socket.setOutboundFileDescriptors(stdoutFd);

311

312

// Send message with stdout file descriptor

313

socket.getOutputStream().write("Check your terminal!".getBytes());

314

socket.getOutputStream().flush();

315

}

316

```

317

318

### Capability Detection

319

320

Check for file descriptor and credential support before using advanced features:

321

322

```java { .api }

323

/**

324

* Capability constants for file descriptor features

325

*/

326

public enum AFSocketCapability {

327

/** File descriptor passing support */

328

CAPABILITY_FILE_DESCRIPTORS,

329

330

/** Peer credential support */

331

CAPABILITY_PEER_CREDENTIALS,

332

333

/** Ancillary message support */

334

CAPABILITY_ANCILLARY_MESSAGES

335

}

336

```

337

338

**Feature Detection Examples:**

339

340

```java

341

import org.newsclub.net.unix.*;

342

343

public class FeatureDetection {

344

public static void main(String[] args) {

345

System.out.println("Advanced Unix Socket Features:");

346

347

if (AFSocketCapability.CAPABILITY_FILE_DESCRIPTORS.isSupported()) {

348

System.out.println("✓ File descriptor passing available");

349

demonstrateFileDescriptorPassing();

350

} else {

351

System.out.println("✗ File descriptor passing not supported");

352

}

353

354

if (AFSocketCapability.CAPABILITY_PEER_CREDENTIALS.isSupported()) {

355

System.out.println("✓ Peer credentials available");

356

demonstratePeerCredentials();

357

} else {

358

System.out.println("✗ Peer credentials not supported");

359

}

360

361

if (AFSocketCapability.CAPABILITY_ANCILLARY_MESSAGES.isSupported()) {

362

System.out.println("✓ Ancillary messages available");

363

} else {

364

System.out.println("✗ Ancillary messages not supported");

365

}

366

}

367

368

private static void demonstrateFileDescriptorPassing() {

369

// File descriptor passing implementation

370

System.out.println(" → File descriptor passing is fully functional");

371

}

372

373

private static void demonstratePeerCredentials() {

374

// Peer credentials implementation

375

AFUNIXSocketCredentials current = AFUNIXSocketCredentials.current();

376

System.out.println(" → Current process PID: " + current.getPid());

377

System.out.println(" → Current process UID: " + current.getUid());

378

}

379

}

380

```

381

382

### Security Considerations

383

384

When using file descriptor passing and peer credentials:

385

386

1. **Validate Received File Descriptors**: Always validate file descriptors before use

387

2. **Check Permissions**: Verify peer credentials for authorization

388

3. **Resource Management**: Properly close received file descriptors

389

4. **Error Handling**: Handle cases where features are not supported

390

5. **Capability Testing**: Always test capabilities before using advanced features

391

392

```java

393

// Safe file descriptor handling

394

FileDescriptor[] receivedFds = socket.getReceivedFileDescriptors();

395

for (FileDescriptor fd : receivedFds) {

396

if (FileDescriptorAccess.isValid(fd)) {

397

try {

398

// Use the file descriptor

399

processFileDescriptor(fd);

400

} finally {

401

// Ensure proper cleanup

402

try {

403

// Close if it's a file we opened

404

if (fd != FileDescriptor.in && fd != FileDescriptor.out && fd != FileDescriptor.err) {

405

// Close safely

406

}

407

} catch (Exception e) {

408

// Log but don't fail

409

}

410

}

411

}

412

}

413

socket.clearReceivedFileDescriptors();

414

```