1 /*
2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
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
117 throws UnixException
118 {
119 Flags flags = Flags.toFlags(options);
120
121 // default is reading; append => writing
122 if (!flags.read && !flags.write) {
123 if (flags.append) {
124 flags.write = true;
125 } else {
126 flags.read = true;
127 }
128 }
129
130 // validation
131 if (flags.read && flags.append)
132 throw new IllegalArgumentException("READ + APPEND not allowed");
133 if (flags.append && flags.truncateExisting)
134 throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
135
136 FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
137 return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, null);
138 }
139
140 /**
141 * Constructs a file channel by opening the given file.
142 */
143 static FileChannel newFileChannel(UnixPath path,
144 Set<? extends OpenOption> options,
145 int mode)
146 throws UnixException
147 {
148 return newFileChannel(-1, path, null, options, mode);
149 }
150
151 /**
152 * Constructs an asynchronous file channel by opening the given file.
153 */
154 static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,
155 Set<? extends OpenOption> options,
156 int mode,
157 ThreadPool pool)
218 // follow links by default
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);
|
1 /*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
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
124 throws UnixException
125 {
126 Flags flags = Flags.toFlags(options);
127
128 // default is reading; append => writing
129 if (!flags.read && !flags.write) {
130 if (flags.append) {
131 flags.write = true;
132 } else {
133 flags.read = true;
134 }
135 }
136
137 // validation
138 if (flags.read && flags.append)
139 throw new IllegalArgumentException("READ + APPEND not allowed");
140 if (flags.append && flags.truncateExisting)
141 throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
142
143 FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
144 return FileChannelImpl.open(fdObj, path.toString(), flags.read,
145 flags.write, flags.direct, null);
146 }
147
148 /**
149 * Constructs a file channel by opening the given file.
150 */
151 static FileChannel newFileChannel(UnixPath path,
152 Set<? extends OpenOption> options,
153 int mode)
154 throws UnixException
155 {
156 return newFileChannel(-1, path, null, options, mode);
157 }
158
159 /**
160 * Constructs an asynchronous file channel by opening the given file.
161 */
162 static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,
163 Set<? extends OpenOption> options,
164 int mode,
165 ThreadPool pool)
226 // follow links by default
227 boolean followLinks = true;
228 if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {
229 if (flags.deleteOnClose && O_NOFOLLOW == 0) {
230 try {
231 if (UnixFileAttributes.get(path, false).isSymbolicLink())
232 throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link");
233 } catch (UnixException x) {
234 if (!flags.create || x.errno() != ENOENT)
235 throw x;
236 }
237 }
238 followLinks = false;
239 oflags |= O_NOFOLLOW;
240 }
241
242 if (flags.dsync)
243 oflags |= O_DSYNC;
244 if (flags.sync)
245 oflags |= O_SYNC;
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);
|