SecureDS.java revision 3909:272483f6650b
1/*
2 * Copyright (c) 2008, 2011, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* @test
25 * @bug 4313887 6838333
26 * @summary Unit test for java.nio.file.SecureDirectoryStream
27 * @library ..
28 */
29
30import java.nio.file.*;
31import static java.nio.file.Files.*;
32import static java.nio.file.StandardOpenOption.*;
33import static java.nio.file.LinkOption.*;
34import java.nio.file.attribute.*;
35import java.nio.channels.*;
36import java.io.IOException;
37import java.util.*;
38
39public class SecureDS {
40    static boolean supportsLinks;
41
42    public static void main(String[] args) throws IOException {
43        Path dir = TestUtil.createTemporaryDirectory();
44        try {
45            DirectoryStream<Path> stream = newDirectoryStream(dir);
46            stream.close();
47            if (!(stream instanceof SecureDirectoryStream)) {
48                System.out.println("SecureDirectoryStream not supported.");
49                return;
50            }
51
52            supportsLinks = TestUtil.supportsLinks(dir);
53
54            // run tests
55            doBasicTests(dir);
56            doMoveTests(dir);
57            miscTests(dir);
58
59        } finally {
60            TestUtil.removeAll(dir);
61        }
62    }
63
64    // Exercise each of SecureDirectoryStream's method (except move)
65    static void doBasicTests(Path dir) throws IOException {
66        Path dir1 = createDirectory(dir.resolve("dir1"));
67        Path dir2 = dir.resolve("dir2");
68
69        // create a file, directory, and two sym links in the directory
70        Path fileEntry = Paths.get("myfile");
71        createFile(dir1.resolve(fileEntry));
72        Path dirEntry = Paths.get("mydir");
73        createDirectory(dir1.resolve(dirEntry));
74        // myfilelink -> myfile
75        Path link1Entry = Paths.get("myfilelink");
76        if (supportsLinks)
77            createSymbolicLink(dir1.resolve(link1Entry), fileEntry);
78        // mydirlink -> mydir
79        Path link2Entry = Paths.get("mydirlink");
80        if (supportsLinks)
81            createSymbolicLink(dir1.resolve(link2Entry), dirEntry);
82
83        // open directory and then move it so that it is no longer accessible
84        // via its original path.
85        SecureDirectoryStream<Path> stream =
86            (SecureDirectoryStream<Path>)newDirectoryStream(dir1);
87        move(dir1, dir2);
88
89        // Test: iterate over all entries
90        int count = 0;
91        for (Path entry: stream) { count++; }
92        assertTrue(count == (supportsLinks ? 4 : 2));
93
94        // Test: getFileAttributeView to access directory's attributes
95        assertTrue(stream
96            .getFileAttributeView(BasicFileAttributeView.class)
97                .readAttributes()
98                    .isDirectory());
99
100        // Test: getFileAttributeView to access attributes of entries
101        assertTrue(stream
102            .getFileAttributeView(fileEntry, BasicFileAttributeView.class)
103                .readAttributes()
104                    .isRegularFile());
105        assertTrue(stream
106            .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
107                .readAttributes()
108                    .isRegularFile());
109        assertTrue(stream
110            .getFileAttributeView(dirEntry, BasicFileAttributeView.class)
111                .readAttributes()
112                    .isDirectory());
113        assertTrue(stream
114            .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
115                .readAttributes()
116                    .isDirectory());
117        if (supportsLinks) {
118            assertTrue(stream
119                .getFileAttributeView(link1Entry, BasicFileAttributeView.class)
120                    .readAttributes()
121                        .isRegularFile());
122            assertTrue(stream
123                .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
124                    .readAttributes()
125                        .isSymbolicLink());
126            assertTrue(stream
127                .getFileAttributeView(link2Entry, BasicFileAttributeView.class)
128                    .readAttributes()
129                        .isDirectory());
130            assertTrue(stream
131                .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
132                    .readAttributes()
133                        .isSymbolicLink());
134        }
135
136        // Test: newByteChannel
137        Set<StandardOpenOption> opts = Collections.emptySet();
138        stream.newByteChannel(fileEntry, opts).close();
139        if (supportsLinks) {
140            stream.newByteChannel(link1Entry, opts).close();
141            try {
142                Set<OpenOption> mixed = new HashSet<>();
143                mixed.add(READ);
144                mixed.add(NOFOLLOW_LINKS);
145                stream.newByteChannel(link1Entry, mixed).close();
146                shouldNotGetHere();
147            } catch (IOException x) { }
148        }
149
150        // Test: newDirectoryStream
151        stream.newDirectoryStream(dirEntry).close();
152        stream.newDirectoryStream(dirEntry, LinkOption.NOFOLLOW_LINKS).close();
153        if (supportsLinks) {
154            stream.newDirectoryStream(link2Entry).close();
155            try {
156                stream.newDirectoryStream(link2Entry, LinkOption.NOFOLLOW_LINKS)
157                    .close();
158                shouldNotGetHere();
159            } catch (IOException x) { }
160        }
161
162        // Test: delete
163        if (supportsLinks) {
164            stream.deleteFile(link1Entry);
165            stream.deleteFile(link2Entry);
166        }
167        stream.deleteDirectory(dirEntry);
168        stream.deleteFile(fileEntry);
169
170        // clean-up
171        stream.close();
172        delete(dir2);
173    }
174
175    // Exercise SecureDirectoryStream's move method
176    static void doMoveTests(Path dir) throws IOException {
177        Path dir1 = createDirectory(dir.resolve("dir1"));
178        Path dir2 = createDirectory(dir.resolve("dir2"));
179
180        // create dir1/myfile, dir1/mydir, dir1/mylink
181        Path fileEntry = Paths.get("myfile");
182        createFile(dir1.resolve(fileEntry));
183        Path dirEntry = Paths.get("mydir");
184        createDirectory(dir1.resolve(dirEntry));
185        Path linkEntry = Paths.get("mylink");
186        if (supportsLinks)
187            createSymbolicLink(dir1.resolve(linkEntry), Paths.get("missing"));
188
189        // target name
190        Path target = Paths.get("newfile");
191
192        // open stream to both directories
193        SecureDirectoryStream<Path> stream1 =
194            (SecureDirectoryStream<Path>)newDirectoryStream(dir1);
195        SecureDirectoryStream<Path> stream2 =
196            (SecureDirectoryStream<Path>)newDirectoryStream(dir2);
197
198        // Test: move dir1/myfile -> dir2/newfile
199        stream1.move(fileEntry, stream2, target);
200        assertTrue(notExists(dir1.resolve(fileEntry)));
201        assertTrue(exists(dir2.resolve(target)));
202        stream2.deleteFile(target);
203
204        // Test: move dir1/mydir -> dir2/newfile
205        stream1.move(dirEntry, stream2, target);
206        assertTrue(notExists(dir1.resolve(dirEntry)));
207        assertTrue(exists(dir2.resolve(target)));
208        stream2.deleteDirectory(target);
209
210        // Test: move dir1/mylink -> dir2/newfile
211        if (supportsLinks) {
212            stream1.move(linkEntry, stream2, target);
213            assertTrue(isSymbolicLink(dir2.resolve(target)));
214            stream2.deleteFile(target);
215        }
216
217        // Test: move between devices
218        String testDirAsString = System.getProperty("test.dir");
219        if (testDirAsString != null) {
220            Path testDir = Paths.get(testDirAsString);
221            if (!getFileStore(dir1).equals(getFileStore(testDir))) {
222                SecureDirectoryStream<Path> ts =
223                    (SecureDirectoryStream<Path>)newDirectoryStream(testDir);
224                createFile(dir1.resolve(fileEntry));
225                try {
226                    stream1.move(fileEntry, ts, target);
227                    shouldNotGetHere();
228                } catch (AtomicMoveNotSupportedException x) { }
229                ts.close();
230                stream1.deleteFile(fileEntry);
231            }
232        }
233
234        // clean-up
235        delete(dir1);
236        delete(dir2);
237    }
238
239    // null and ClosedDirectoryStreamException
240    static void miscTests(Path dir) throws IOException {
241        Path file = Paths.get("file");
242        createFile(dir.resolve(file));
243
244        SecureDirectoryStream<Path> stream =
245            (SecureDirectoryStream<Path>)newDirectoryStream(dir);
246
247        // NullPointerException
248        try {
249            stream.getFileAttributeView(null);
250            shouldNotGetHere();
251        } catch (NullPointerException x) { }
252        try {
253            stream.getFileAttributeView(null, BasicFileAttributeView.class);
254            shouldNotGetHere();
255        } catch (NullPointerException x) { }
256        try {
257            stream.getFileAttributeView(file, null);
258            shouldNotGetHere();
259        } catch (NullPointerException x) { }
260        try {
261            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE));
262            shouldNotGetHere();
263        } catch (NullPointerException x) { }
264        try {
265            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null));
266            shouldNotGetHere();
267        } catch (NullPointerException x) { }
268        try {
269            stream.newByteChannel(file, null);
270            shouldNotGetHere();
271        } catch (NullPointerException x) { }
272        try {
273            stream.move(null, stream, file);
274            shouldNotGetHere();
275        } catch (NullPointerException x) { }
276        try {
277            stream.move(file, null, file);
278            shouldNotGetHere();
279        } catch (NullPointerException x) { }
280        try {
281            stream.move(file, stream, null);
282            shouldNotGetHere();
283        } catch (NullPointerException x) { }
284        try {
285            stream.newDirectoryStream(null);
286            shouldNotGetHere();
287        } catch (NullPointerException x) { }
288        try {
289            stream.deleteFile(null);
290            shouldNotGetHere();
291        } catch (NullPointerException x) { }
292        try {
293            stream.deleteDirectory(null);
294            shouldNotGetHere();
295        } catch (NullPointerException x) { }
296
297        // close stream
298        stream.close();
299        stream.close();     // should be no-op
300
301        // ClosedDirectoryStreamException
302        try {
303            stream.newDirectoryStream(file);
304            shouldNotGetHere();
305        } catch (ClosedDirectoryStreamException x) { }
306        try {
307            stream.newByteChannel(file, EnumSet.of(READ));
308            shouldNotGetHere();
309        } catch (ClosedDirectoryStreamException x) { }
310        try {
311            stream.move(file, stream, file);
312            shouldNotGetHere();
313        } catch (ClosedDirectoryStreamException x) { }
314        try {
315            stream.deleteFile(file);
316            shouldNotGetHere();
317        } catch (ClosedDirectoryStreamException x) { }
318
319        // clean-up
320        delete(dir.resolve(file));
321    }
322
323    static void assertTrue(boolean b) {
324        if (!b) throw new RuntimeException("Assertion failed");
325    }
326
327    static void shouldNotGetHere() {
328        assertTrue(false);
329    }
330}
331