SecureDS.java revision 15567:08bbb5882450
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                if (System.getProperty("os.name").equals("Linux"))
49                    throw new AssertionError(
50                            "SecureDirectoryStream not supported.");
51                System.out.println("SecureDirectoryStream not supported.");
52                return;
53            }
54
55            supportsLinks = TestUtil.supportsLinks(dir);
56
57            // run tests
58            doBasicTests(dir);
59            doMoveTests(dir);
60            miscTests(dir);
61
62        } finally {
63            TestUtil.removeAll(dir);
64        }
65    }
66
67    // Exercise each of SecureDirectoryStream's method (except move)
68    static void doBasicTests(Path dir) throws IOException {
69        Path dir1 = createDirectory(dir.resolve("dir1"));
70        Path dir2 = dir.resolve("dir2");
71
72        // create a file, directory, and two sym links in the directory
73        Path fileEntry = Paths.get("myfile");
74        createFile(dir1.resolve(fileEntry));
75        Path dirEntry = Paths.get("mydir");
76        createDirectory(dir1.resolve(dirEntry));
77        // myfilelink -> myfile
78        Path link1Entry = Paths.get("myfilelink");
79        if (supportsLinks)
80            createSymbolicLink(dir1.resolve(link1Entry), fileEntry);
81        // mydirlink -> mydir
82        Path link2Entry = Paths.get("mydirlink");
83        if (supportsLinks)
84            createSymbolicLink(dir1.resolve(link2Entry), dirEntry);
85
86        // open directory and then move it so that it is no longer accessible
87        // via its original path.
88        SecureDirectoryStream<Path> stream =
89            (SecureDirectoryStream<Path>)newDirectoryStream(dir1);
90        move(dir1, dir2);
91
92        // Test: iterate over all entries
93        int count = 0;
94        for (Path entry: stream) { count++; }
95        assertTrue(count == (supportsLinks ? 4 : 2));
96
97        // Test: getFileAttributeView to access directory's attributes
98        assertTrue(stream
99            .getFileAttributeView(BasicFileAttributeView.class)
100                .readAttributes()
101                    .isDirectory());
102
103        // Test: getFileAttributeView to access attributes of entries
104        assertTrue(stream
105            .getFileAttributeView(fileEntry, BasicFileAttributeView.class)
106                .readAttributes()
107                    .isRegularFile());
108        assertTrue(stream
109            .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
110                .readAttributes()
111                    .isRegularFile());
112        assertTrue(stream
113            .getFileAttributeView(dirEntry, BasicFileAttributeView.class)
114                .readAttributes()
115                    .isDirectory());
116        assertTrue(stream
117            .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
118                .readAttributes()
119                    .isDirectory());
120        if (supportsLinks) {
121            assertTrue(stream
122                .getFileAttributeView(link1Entry, BasicFileAttributeView.class)
123                    .readAttributes()
124                        .isRegularFile());
125            assertTrue(stream
126                .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
127                    .readAttributes()
128                        .isSymbolicLink());
129            assertTrue(stream
130                .getFileAttributeView(link2Entry, BasicFileAttributeView.class)
131                    .readAttributes()
132                        .isDirectory());
133            assertTrue(stream
134                .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS)
135                    .readAttributes()
136                        .isSymbolicLink());
137        }
138
139        // Test: newByteChannel
140        Set<StandardOpenOption> opts = Collections.emptySet();
141        stream.newByteChannel(fileEntry, opts).close();
142        if (supportsLinks) {
143            stream.newByteChannel(link1Entry, opts).close();
144            try {
145                Set<OpenOption> mixed = new HashSet<>();
146                mixed.add(READ);
147                mixed.add(NOFOLLOW_LINKS);
148                stream.newByteChannel(link1Entry, mixed).close();
149                shouldNotGetHere();
150            } catch (IOException x) { }
151        }
152
153        // Test: newDirectoryStream
154        stream.newDirectoryStream(dirEntry).close();
155        stream.newDirectoryStream(dirEntry, LinkOption.NOFOLLOW_LINKS).close();
156        if (supportsLinks) {
157            stream.newDirectoryStream(link2Entry).close();
158            try {
159                stream.newDirectoryStream(link2Entry, LinkOption.NOFOLLOW_LINKS)
160                    .close();
161                shouldNotGetHere();
162            } catch (IOException x) { }
163        }
164
165        // Test: delete
166        if (supportsLinks) {
167            stream.deleteFile(link1Entry);
168            stream.deleteFile(link2Entry);
169        }
170        stream.deleteDirectory(dirEntry);
171        stream.deleteFile(fileEntry);
172
173        // clean-up
174        stream.close();
175        delete(dir2);
176    }
177
178    // Exercise SecureDirectoryStream's move method
179    static void doMoveTests(Path dir) throws IOException {
180        Path dir1 = createDirectory(dir.resolve("dir1"));
181        Path dir2 = createDirectory(dir.resolve("dir2"));
182
183        // create dir1/myfile, dir1/mydir, dir1/mylink
184        Path fileEntry = Paths.get("myfile");
185        createFile(dir1.resolve(fileEntry));
186        Path dirEntry = Paths.get("mydir");
187        createDirectory(dir1.resolve(dirEntry));
188        Path linkEntry = Paths.get("mylink");
189        if (supportsLinks)
190            createSymbolicLink(dir1.resolve(linkEntry), Paths.get("missing"));
191
192        // target name
193        Path target = Paths.get("newfile");
194
195        // open stream to both directories
196        SecureDirectoryStream<Path> stream1 =
197            (SecureDirectoryStream<Path>)newDirectoryStream(dir1);
198        SecureDirectoryStream<Path> stream2 =
199            (SecureDirectoryStream<Path>)newDirectoryStream(dir2);
200
201        // Test: move dir1/myfile -> dir2/newfile
202        stream1.move(fileEntry, stream2, target);
203        assertTrue(notExists(dir1.resolve(fileEntry)));
204        assertTrue(exists(dir2.resolve(target)));
205        stream2.deleteFile(target);
206
207        // Test: move dir1/mydir -> dir2/newfile
208        stream1.move(dirEntry, stream2, target);
209        assertTrue(notExists(dir1.resolve(dirEntry)));
210        assertTrue(exists(dir2.resolve(target)));
211        stream2.deleteDirectory(target);
212
213        // Test: move dir1/mylink -> dir2/newfile
214        if (supportsLinks) {
215            stream1.move(linkEntry, stream2, target);
216            assertTrue(isSymbolicLink(dir2.resolve(target)));
217            stream2.deleteFile(target);
218        }
219
220        // Test: move between devices
221        String testDirAsString = System.getProperty("test.dir");
222        if (testDirAsString != null) {
223            Path testDir = Paths.get(testDirAsString);
224            if (!getFileStore(dir1).equals(getFileStore(testDir))) {
225                SecureDirectoryStream<Path> ts =
226                    (SecureDirectoryStream<Path>)newDirectoryStream(testDir);
227                createFile(dir1.resolve(fileEntry));
228                try {
229                    stream1.move(fileEntry, ts, target);
230                    shouldNotGetHere();
231                } catch (AtomicMoveNotSupportedException x) { }
232                ts.close();
233                stream1.deleteFile(fileEntry);
234            }
235        }
236
237        // clean-up
238        delete(dir1);
239        delete(dir2);
240    }
241
242    // null and ClosedDirectoryStreamException
243    static void miscTests(Path dir) throws IOException {
244        Path file = Paths.get("file");
245        createFile(dir.resolve(file));
246
247        SecureDirectoryStream<Path> stream =
248            (SecureDirectoryStream<Path>)newDirectoryStream(dir);
249
250        // NullPointerException
251        try {
252            stream.getFileAttributeView(null);
253            shouldNotGetHere();
254        } catch (NullPointerException x) { }
255        try {
256            stream.getFileAttributeView(null, BasicFileAttributeView.class);
257            shouldNotGetHere();
258        } catch (NullPointerException x) { }
259        try {
260            stream.getFileAttributeView(file, null);
261            shouldNotGetHere();
262        } catch (NullPointerException x) { }
263        try {
264            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE));
265            shouldNotGetHere();
266        } catch (NullPointerException x) { }
267        try {
268            stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null));
269            shouldNotGetHere();
270        } catch (NullPointerException x) { }
271        try {
272            stream.newByteChannel(file, null);
273            shouldNotGetHere();
274        } catch (NullPointerException x) { }
275        try {
276            stream.move(null, stream, file);
277            shouldNotGetHere();
278        } catch (NullPointerException x) { }
279        try {
280            stream.move(file, null, file);
281            shouldNotGetHere();
282        } catch (NullPointerException x) { }
283        try {
284            stream.move(file, stream, null);
285            shouldNotGetHere();
286        } catch (NullPointerException x) { }
287        try {
288            stream.newDirectoryStream(null);
289            shouldNotGetHere();
290        } catch (NullPointerException x) { }
291        try {
292            stream.deleteFile(null);
293            shouldNotGetHere();
294        } catch (NullPointerException x) { }
295        try {
296            stream.deleteDirectory(null);
297            shouldNotGetHere();
298        } catch (NullPointerException x) { }
299
300        // close stream
301        stream.close();
302        stream.close();     // should be no-op
303
304        // ClosedDirectoryStreamException
305        try {
306            stream.newDirectoryStream(file);
307            shouldNotGetHere();
308        } catch (ClosedDirectoryStreamException x) { }
309        try {
310            stream.newByteChannel(file, EnumSet.of(READ));
311            shouldNotGetHere();
312        } catch (ClosedDirectoryStreamException x) { }
313        try {
314            stream.move(file, stream, file);
315            shouldNotGetHere();
316        } catch (ClosedDirectoryStreamException x) { }
317        try {
318            stream.deleteFile(file);
319            shouldNotGetHere();
320        } catch (ClosedDirectoryStreamException x) { }
321
322        // clean-up
323        delete(dir.resolve(file));
324    }
325
326    static void assertTrue(boolean b) {
327        if (!b) throw new RuntimeException("Assertion failed");
328    }
329
330    static void shouldNotGetHere() {
331        assertTrue(false);
332    }
333}
334