47 private static final JavaIOFileDescriptorAccess fdAccess =
48 SharedSecrets.getJavaIOFileDescriptorAccess();
49
50 protected UnixChannelFactory() {
51 }
52
53 /**
54 * Represents the flags from a user-supplied set of open options.
55 */
56 protected static class Flags {
57 boolean read;
58 boolean write;
59 boolean append;
60 boolean truncateExisting;
61 boolean noFollowLinks;
62 boolean create;
63 boolean createNew;
64 boolean deleteOnClose;
65 boolean sync;
66 boolean dsync;
67
68 static Flags toFlags(Set<? extends OpenOption> options) {
69 Flags flags = new Flags();
70 for (OpenOption option: options) {
71 if (option instanceof StandardOpenOption) {
72 switch ((StandardOpenOption)option) {
73 case READ : flags.read = true; break;
74 case WRITE : flags.write = true; break;
75 case APPEND : flags.append = true; break;
76 case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
77 case CREATE : flags.create = true; break;
78 case CREATE_NEW : flags.createNew = true; break;
79 case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
80 case SPARSE : /* ignore */ break;
81 case SYNC : flags.sync = true; break;
82 case DSYNC : flags.dsync = true; break;
83 default: throw new UnsupportedOperationException();
84 }
85 continue;
86 }
87 if (option == LinkOption.NOFOLLOW_LINKS && O_NOFOLLOW != 0) {
88 flags.noFollowLinks = true;
89 continue;
90 }
91 if (option == null)
92 throw new NullPointerException();
93 throw new UnsupportedOperationException(option + " not supported");
94 }
95 return flags;
96 }
97 }
98
99
100 /**
101 * Constructs a file channel from an existing (open) file descriptor
102 */
103 static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) {
104 FileDescriptor fdObj = new FileDescriptor();
105 fdAccess.set(fdObj, fd);
106 return FileChannelImpl.open(fdObj, path, reading, writing, null);
107 }
108
109 /**
110 * Constructs a file channel by opening a file using a dfd/path pair
219 boolean followLinks = true;
220 if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {
221 if (flags.deleteOnClose && O_NOFOLLOW == 0) {
222 try {
223 if (UnixFileAttributes.get(path, false).isSymbolicLink())
224 throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link");
225 } catch (UnixException x) {
226 if (!flags.create || x.errno() != ENOENT)
227 throw x;
228 }
229 }
230 followLinks = false;
231 oflags |= O_NOFOLLOW;
232 }
233
234 if (flags.dsync)
235 oflags |= O_DSYNC;
236 if (flags.sync)
237 oflags |= O_SYNC;
238
239 // permission check before we open the file
240 SecurityManager sm = System.getSecurityManager();
241 if (sm != null) {
242 if (pathForPermissionCheck == null)
243 pathForPermissionCheck = path.getPathForPermissionCheck();
244 if (flags.read)
245 sm.checkRead(pathForPermissionCheck);
246 if (flags.write)
247 sm.checkWrite(pathForPermissionCheck);
248 if (flags.deleteOnClose)
249 sm.checkDelete(pathForPermissionCheck);
250 }
251
252 int fd;
253 try {
254 if (dfd >= 0) {
255 fd = openat(dfd, path.asByteArray(), oflags, mode);
256 } else {
257 fd = UnixNativeDispatcher.open(path, oflags, mode);
258 }
272
273 // unlink file immediately if delete on close. The spec is clear that
274 // an implementation cannot guarantee to unlink the correct file when
275 // replaced by an attacker after it is opened.
276 if (flags.deleteOnClose) {
277 try {
278 if (dfd >= 0) {
279 unlinkat(dfd, path.asByteArray(), 0);
280 } else {
281 unlink(path);
282 }
283 } catch (UnixException ignore) {
284 // best-effort
285 }
286 }
287
288 // create java.io.FileDescriptor
289 FileDescriptor fdObj = new FileDescriptor();
290 fdAccess.set(fdObj, fd);
291 fdAccess.setAppend(fdObj, flags.append);
292 return fdObj;
293 }
294 }
|
47 private static final JavaIOFileDescriptorAccess fdAccess =
48 SharedSecrets.getJavaIOFileDescriptorAccess();
49
50 protected UnixChannelFactory() {
51 }
52
53 /**
54 * Represents the flags from a user-supplied set of open options.
55 */
56 protected static class Flags {
57 boolean read;
58 boolean write;
59 boolean append;
60 boolean truncateExisting;
61 boolean noFollowLinks;
62 boolean create;
63 boolean createNew;
64 boolean deleteOnClose;
65 boolean sync;
66 boolean dsync;
67 boolean direct;
68
69 static Flags toFlags(Set<? extends OpenOption> options) {
70 Flags flags = new Flags();
71 for (OpenOption option: options) {
72 if (option instanceof StandardOpenOption) {
73 switch ((StandardOpenOption)option) {
74 case READ : flags.read = true; break;
75 case WRITE : flags.write = true; break;
76 case APPEND : flags.append = true; break;
77 case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
78 case CREATE : flags.create = true; break;
79 case CREATE_NEW : flags.createNew = true; break;
80 case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
81 case SPARSE : /* ignore */ break;
82 case SYNC : flags.sync = true; break;
83 case DSYNC : flags.dsync = true; break;
84 default: throw new UnsupportedOperationException();
85 }
86 continue;
87 }
88 if (option == LinkOption.NOFOLLOW_LINKS && O_NOFOLLOW != 0) {
89 flags.noFollowLinks = true;
90 continue;
91 }
92
93 if (ExtendedOptions.DIRECT.matches(option)) {
94 flags.direct = true;
95 continue;
96 }
97
98 if (option == null)
99 throw new NullPointerException();
100 throw new UnsupportedOperationException(option + " not supported");
101 }
102 return flags;
103 }
104 }
105
106
107 /**
108 * Constructs a file channel from an existing (open) file descriptor
109 */
110 static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) {
111 FileDescriptor fdObj = new FileDescriptor();
112 fdAccess.set(fdObj, fd);
113 return FileChannelImpl.open(fdObj, path, reading, writing, null);
114 }
115
116 /**
117 * Constructs a file channel by opening a file using a dfd/path pair
226 boolean followLinks = true;
227 if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {
228 if (flags.deleteOnClose && O_NOFOLLOW == 0) {
229 try {
230 if (UnixFileAttributes.get(path, false).isSymbolicLink())
231 throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link");
232 } catch (UnixException x) {
233 if (!flags.create || x.errno() != ENOENT)
234 throw x;
235 }
236 }
237 followLinks = false;
238 oflags |= O_NOFOLLOW;
239 }
240
241 if (flags.dsync)
242 oflags |= O_DSYNC;
243 if (flags.sync)
244 oflags |= O_SYNC;
245
246 if (flags.direct)
247 oflags |= O_DIRECT;
248
249 // permission check before we open the file
250 SecurityManager sm = System.getSecurityManager();
251 if (sm != null) {
252 if (pathForPermissionCheck == null)
253 pathForPermissionCheck = path.getPathForPermissionCheck();
254 if (flags.read)
255 sm.checkRead(pathForPermissionCheck);
256 if (flags.write)
257 sm.checkWrite(pathForPermissionCheck);
258 if (flags.deleteOnClose)
259 sm.checkDelete(pathForPermissionCheck);
260 }
261
262 int fd;
263 try {
264 if (dfd >= 0) {
265 fd = openat(dfd, path.asByteArray(), oflags, mode);
266 } else {
267 fd = UnixNativeDispatcher.open(path, oflags, mode);
268 }
282
283 // unlink file immediately if delete on close. The spec is clear that
284 // an implementation cannot guarantee to unlink the correct file when
285 // replaced by an attacker after it is opened.
286 if (flags.deleteOnClose) {
287 try {
288 if (dfd >= 0) {
289 unlinkat(dfd, path.asByteArray(), 0);
290 } else {
291 unlink(path);
292 }
293 } catch (UnixException ignore) {
294 // best-effort
295 }
296 }
297
298 // create java.io.FileDescriptor
299 FileDescriptor fdObj = new FileDescriptor();
300 fdAccess.set(fdObj, fd);
301 fdAccess.setAppend(fdObj, flags.append);
302 fdAccess.setDirect(fdObj, flags.direct);
303 return fdObj;
304 }
305 }
|