1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.File;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.io.RandomAccessFile;
24 import java.nio.channels.FileChannel;
25 import java.util.UUID;
26 import java.util.concurrent.atomic.AtomicBoolean;
27
28 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
29
30
31
32
33
34
35 @SuppressFBWarnings("PATH_TRAVERSAL_IN")
36 final class RAFChannelProvider extends RandomAccessFile implements FileDescriptorAccess {
37 private static final File DEV_NULL = new File("/dev/null");
38
39 private final File tempPath;
40 private final FileDescriptor fdObj;
41 private final FileDescriptor rafFdOrig = new FileDescriptor();
42 private final AtomicBoolean closed = new AtomicBoolean(false);
43
44 private RAFChannelProvider(FileDescriptor fdObj) throws IOException {
45 this(fdObj, TempFileUtil.INSTANCE.newPathForUnixDomainSocket(false).toFile());
46 }
47
48 private RAFChannelProvider(FileDescriptor fdObj, File tempPath) throws IOException {
49 this(fdObj, tempPath, true);
50 }
51
52 private RAFChannelProvider(FileDescriptor fdObj, File tempPath, boolean delete)
53 throws IOException {
54 super(tempPath, "rw");
55 NativeUnixSocket.ensureSupported();
56
57 this.tempPath = tempPath;
58 if (delete) {
59 if (!tempPath.delete() && tempPath.exists()) {
60 if (!tempPath.delete()) {
61
62 }
63 tempPath = new File(tempPath.getParentFile(), "jux-" + UUID.randomUUID().toString()
64 + ".sock");
65 if (tempPath.exists()) {
66 throw new IOException("Could not create a temporary path: " + tempPath);
67 }
68 }
69 tempPath.deleteOnExit();
70 }
71
72 this.fdObj = fdObj;
73
74 FileDescriptor rafFdObj = getFD();
75 NativeUnixSocket.copyFileDescriptor(rafFdObj, rafFdOrig);
76 NativeUnixSocket.copyFileDescriptor(fdObj, rafFdObj);
77 }
78
79 @SuppressFBWarnings("EI_EXPOSE_REP")
80 @Override
81 public FileDescriptor getFileDescriptor() {
82 return fdObj;
83 }
84
85 @Override
86 public synchronized void close() throws IOException {
87 if (!closed.getAndSet(true)) {
88 NativeUnixSocket.copyFileDescriptor(rafFdOrig, getFD());
89 if (!tempPath.delete()) {
90
91 }
92 }
93 }
94
95 public static FileChannel getFileChannel(FileDescriptor fd) throws IOException {
96 return getFileChannel0(fd);
97 }
98
99 @SuppressWarnings("resource")
100 private static FileChannel getFileChannel0(FileDescriptor fd) throws IOException {
101 if (DEV_NULL.canRead() && DEV_NULL.canWrite()) {
102 try {
103 return new RAFChannelProvider(fd, DEV_NULL, false).getChannel();
104 } catch (IOException e) {
105
106 }
107 }
108 return new RAFChannelProvider(fd).getChannel();
109 }
110 }