SecureDS.java revision 893:f06f30b29f36
1/* 2 * Copyright 2008-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24/* @test 25 * @bug 4313887 26 * @summary Unit test for java.nio.file.SecureDirectoryStream 27 * @library .. 28 */ 29 30import java.nio.file.*; 31import static java.nio.file.StandardOpenOption.*; 32import static java.nio.file.LinkOption.*; 33import java.nio.file.attribute.*; 34import java.nio.channels.*; 35import java.io.IOException; 36import java.util.*; 37 38public class SecureDS { 39 static boolean supportsLinks; 40 41 public static void main(String[] args) throws IOException { 42 Path dir = TestUtil.createTemporaryDirectory(); 43 try { 44 DirectoryStream stream = dir.newDirectoryStream(); 45 stream.close(); 46 if (!(stream instanceof SecureDirectoryStream)) { 47 System.out.println("SecureDirectoryStream not supported."); 48 return; 49 } 50 51 supportsLinks = TestUtil.supportsLinks(dir); 52 53 // run tests 54 doBasicTests(dir); 55 doMoveTests(dir); 56 miscTests(dir); 57 58 } finally { 59 TestUtil.removeAll(dir); 60 } 61 } 62 63 // Exercise each of SecureDirectoryStream's method (except move) 64 static void doBasicTests(Path dir) throws IOException { 65 Path dir1 = dir.resolve("dir1").createDirectory(); 66 Path dir2 = dir.resolve("dir2"); 67 68 // create a file, directory, and two sym links in the directory 69 Path fileEntry = Paths.get("myfile"); 70 dir1.resolve(fileEntry).createFile(); 71 Path dirEntry = Paths.get("mydir"); 72 dir1.resolve(dirEntry).createDirectory(); 73 // myfilelink -> myfile 74 Path link1Entry = Paths.get("myfilelink"); 75 if (supportsLinks) 76 dir1.resolve(link1Entry).createSymbolicLink(fileEntry); 77 // mydirlink -> mydir 78 Path link2Entry = Paths.get("mydirlink"); 79 if (supportsLinks) 80 dir1.resolve(link2Entry).createSymbolicLink(dirEntry); 81 82 // open directory and then move it so that it is no longer accessible 83 // via its original path. 84 SecureDirectoryStream stream = 85 (SecureDirectoryStream)dir1.newDirectoryStream(); 86 dir1.moveTo(dir2); 87 88 // Test: iterate over all entries 89 int count = 0; 90 for (Path entry: stream) { count++; } 91 assertTrue(count == (supportsLinks ? 4 : 2)); 92 93 // Test: getFileAttributeView to access directory's attributes 94 assertTrue(stream 95 .getFileAttributeView(BasicFileAttributeView.class) 96 .readAttributes() 97 .isDirectory()); 98 99 // Test: dynamic access to directory's attributes 100 BasicFileAttributeView view = stream. 101 getFileAttributeView(BasicFileAttributeView.class); 102 Map<String,?> attrs = view.readAttributes("*"); 103 assertTrue((Boolean)attrs.get("isDirectory")); 104 attrs = view.readAttributes("isRegularFile", "size"); 105 assertTrue(!(Boolean)attrs.get("isRegularFile")); 106 assertTrue((Long)attrs.get("size") >= 0); 107 int linkCount = (Integer)view.getAttribute("linkCount"); 108 assertTrue(linkCount > 0); 109 view.setAttribute("lastModifiedTime", 0L); 110 111 // Test: getFileAttributeView to access attributes of entries 112 assertTrue(stream 113 .getFileAttributeView(fileEntry, BasicFileAttributeView.class) 114 .readAttributes() 115 .isRegularFile()); 116 assertTrue(stream 117 .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) 118 .readAttributes() 119 .isRegularFile()); 120 assertTrue(stream 121 .getFileAttributeView(dirEntry, BasicFileAttributeView.class) 122 .readAttributes() 123 .isDirectory()); 124 assertTrue(stream 125 .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) 126 .readAttributes() 127 .isDirectory()); 128 if (supportsLinks) { 129 assertTrue(stream 130 .getFileAttributeView(link1Entry, BasicFileAttributeView.class) 131 .readAttributes() 132 .isRegularFile()); 133 assertTrue(stream 134 .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) 135 .readAttributes() 136 .isSymbolicLink()); 137 assertTrue(stream 138 .getFileAttributeView(link2Entry, BasicFileAttributeView.class) 139 .readAttributes() 140 .isDirectory()); 141 assertTrue(stream 142 .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) 143 .readAttributes() 144 .isSymbolicLink()); 145 } 146 147 // Test: dynamic access to entry attributes 148 view = stream 149 .getFileAttributeView(fileEntry, PosixFileAttributeView.class, NOFOLLOW_LINKS); 150 if (view != null) { 151 attrs = view.readAttributes("owner", "size"); 152 UserPrincipal owner = (UserPrincipal)attrs.get("owner"); 153 assertTrue(owner != null); 154 assertTrue((Long)attrs.get("size") >= 0L); 155 view.setAttribute("lastAccessTime", 0L); 156 } 157 158 // Test: newByteChannel 159 Set<StandardOpenOption> opts = Collections.emptySet(); 160 stream.newByteChannel(fileEntry, opts).close(); 161 if (supportsLinks) { 162 stream.newByteChannel(link1Entry, opts).close(); 163 try { 164 Set<OpenOption> mixed = new HashSet<OpenOption>(); 165 mixed.add(READ); 166 mixed.add(NOFOLLOW_LINKS); 167 stream.newByteChannel(link1Entry, mixed).close(); 168 shouldNotGetHere(); 169 } catch (IOException x) { } 170 } 171 172 // Test: newDirectoryStream 173 stream.newDirectoryStream(dirEntry, true, null).close(); 174 stream.newDirectoryStream(dirEntry, false, null).close(); 175 if (supportsLinks) { 176 stream.newDirectoryStream(link2Entry, true, null).close(); 177 try { 178 stream.newDirectoryStream(link2Entry, false, null).close(); 179 shouldNotGetHere(); 180 } catch (IOException x) { } 181 } 182 183 // Test: delete 184 if (supportsLinks) { 185 stream.deleteFile(link1Entry); 186 stream.deleteFile(link2Entry); 187 } 188 stream.deleteDirectory(dirEntry); 189 stream.deleteFile(fileEntry); 190 191 // Test: remove 192 // (requires resetting environment to get new iterator) 193 stream.close(); 194 dir2.moveTo(dir1); 195 dir1.resolve(fileEntry).createFile(); 196 stream = (SecureDirectoryStream)dir1.newDirectoryStream(); 197 dir1.moveTo(dir2); 198 Iterator<Path> iter = stream.iterator(); 199 int removed = 0; 200 while (iter.hasNext()) { 201 iter.next(); 202 iter.remove(); 203 removed++; 204 } 205 assertTrue(removed == 1); 206 207 // clean-up 208 stream.close(); 209 dir2.delete(); 210 } 211 212 // Exercise SecureDirectoryStream's move method 213 static void doMoveTests(Path dir) throws IOException { 214 Path dir1 = dir.resolve("dir1").createDirectory(); 215 Path dir2 = dir.resolve("dir2").createDirectory(); 216 217 // create dir1/myfile, dir1/mydir, dir1/mylink 218 Path fileEntry = Paths.get("myfile"); 219 dir1.resolve(fileEntry).createFile(); 220 Path dirEntry = Paths.get("mydir"); 221 dir1.resolve(dirEntry).createDirectory(); 222 Path linkEntry = Paths.get("mylink"); 223 if (supportsLinks) 224 dir1.resolve(linkEntry).createSymbolicLink(Paths.get("missing")); 225 226 // target name 227 Path target = Paths.get("newfile"); 228 229 // open stream to both directories 230 SecureDirectoryStream stream1 = 231 (SecureDirectoryStream)dir1.newDirectoryStream(); 232 SecureDirectoryStream stream2 = 233 (SecureDirectoryStream)dir2.newDirectoryStream(); 234 235 // Test: move dir1/myfile -> dir2/newfile 236 stream1.move(fileEntry, stream2, target); 237 assertTrue(dir1.resolve(fileEntry).notExists()); 238 assertTrue(dir2.resolve(target).exists()); 239 stream2.deleteFile(target); 240 241 // Test: move dir1/mydir -> dir2/newfile 242 stream1.move(dirEntry, stream2, target); 243 assertTrue(dir1.resolve(dirEntry).notExists()); 244 assertTrue(dir2.resolve(target).exists()); 245 stream2.deleteDirectory(target); 246 247 // Test: move dir1/mylink -> dir2/newfile 248 if (supportsLinks) { 249 stream1.move(linkEntry, stream2, target); 250 assertTrue(dir2.resolve(target) 251 .getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) 252 .readAttributes() 253 .isSymbolicLink()); 254 stream2.deleteFile(target); 255 } 256 257 // Test: move between devices 258 String testDirAsString = System.getProperty("test.dir"); 259 if (testDirAsString != null) { 260 Path testDir = Paths.get(testDirAsString); 261 if (!dir1.getFileStore().equals(testDir.getFileStore())) { 262 SecureDirectoryStream ts = 263 (SecureDirectoryStream)testDir.newDirectoryStream(); 264 dir1.resolve(fileEntry).createFile(); 265 try { 266 stream1.move(fileEntry, ts, target); 267 shouldNotGetHere(); 268 } catch (AtomicMoveNotSupportedException x) { } 269 ts.close(); 270 stream1.deleteFile(fileEntry); 271 } 272 } 273 274 // clean-up 275 dir1.delete(); 276 dir2.delete(); 277 } 278 279 // null and ClosedDirectoryStreamException 280 static void miscTests(Path dir) throws IOException { 281 Path file = Paths.get("file"); 282 dir.resolve(file).createFile(); 283 284 SecureDirectoryStream stream = 285 (SecureDirectoryStream)dir.newDirectoryStream(); 286 287 // NullPointerException 288 try { 289 stream.getFileAttributeView(null); 290 shouldNotGetHere(); 291 } catch (NullPointerException x) { } 292 try { 293 stream.getFileAttributeView(null, BasicFileAttributeView.class); 294 shouldNotGetHere(); 295 } catch (NullPointerException x) { } 296 try { 297 stream.getFileAttributeView(file, null); 298 shouldNotGetHere(); 299 } catch (NullPointerException x) { } 300 try { 301 stream.newByteChannel(null, EnumSet.of(CREATE,WRITE)); 302 shouldNotGetHere(); 303 } catch (NullPointerException x) { } 304 try { 305 stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null)); 306 shouldNotGetHere(); 307 } catch (NullPointerException x) { } 308 try { 309 stream.newByteChannel(file, null); 310 shouldNotGetHere(); 311 } catch (NullPointerException x) { } 312 try { 313 stream.move(null, stream, file); 314 shouldNotGetHere(); 315 } catch (NullPointerException x) { } 316 try { 317 stream.move(file, null, file); 318 shouldNotGetHere(); 319 } catch (NullPointerException x) { } 320 try { 321 stream.move(file, stream, null); 322 shouldNotGetHere(); 323 } catch (NullPointerException x) { } 324 try { 325 stream.newDirectoryStream(null, true, null); 326 shouldNotGetHere(); 327 } catch (NullPointerException x) { } 328 try { 329 stream.deleteFile(null); 330 shouldNotGetHere(); 331 } catch (NullPointerException x) { } 332 try { 333 stream.deleteDirectory(null); 334 shouldNotGetHere(); 335 } catch (NullPointerException x) { } 336 337 // close stream 338 stream.close(); 339 stream.close(); // should be no-op 340 341 // ClosedDirectoryStreamException 342 try { 343 stream.newDirectoryStream(file, true, null); 344 shouldNotGetHere(); 345 } catch (ClosedDirectoryStreamException x) { } 346 try { 347 stream.newByteChannel(file, EnumSet.of(READ)); 348 shouldNotGetHere(); 349 } catch (ClosedDirectoryStreamException x) { } 350 try { 351 stream.move(file, stream, file); 352 shouldNotGetHere(); 353 } catch (ClosedDirectoryStreamException x) { } 354 try { 355 stream.deleteFile(file); 356 shouldNotGetHere(); 357 } catch (ClosedDirectoryStreamException x) { } 358 359 // clean-up 360 dir.resolve(file).delete(); 361 } 362 363 static void assertTrue(boolean b) { 364 if (!b) throw new RuntimeException("Assertion failed"); 365 } 366 367 static void shouldNotGetHere() { 368 assertTrue(false); 369 } 370} 371