1 /* 2 * Copyright (c) 2005, 2012, 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 /** 25 * @test 26 * @bug 4057701 6286712 6364377 27 * @ignore until 6492634 and 6501010 is fixed 28 * @run build GetXSpace 29 * @run shell GetXSpace.sh 30 * @summary Basic functionality of File.get-X-Space methods. 31 * @key randomness 32 */ 33 34 import java.io.BufferedReader; 35 import java.io.File; 36 import java.io.FilePermission; 37 import java.io.InputStreamReader; 38 import java.io.IOException; 39 import java.security.Permission; 40 import java.util.ArrayList; 41 import java.util.regex.Matcher; 42 import java.util.regex.Pattern; 43 44 import static java.lang.System.out; 45 46 public class GetXSpace { 47 48 private static SecurityManager [] sma = { null, new Allow(), new DenyFSA(), 49 new DenyRead() }; 50 51 private static final String name = System.getProperty("os.name"); 52 private static final String dfFormat; 53 static { 54 if (name.equals("SunOS") || name.equals("Linux") 55 || name.contains("OS X")) { 56 // FileSystem Total Used Available Use% MountedOn 57 dfFormat = "([^\\s]+)\\s+(\\d+)\\s+\\d+\\s+(\\d+)\\s+\\d+%\\s+([^\\s]+)"; 58 } else if (name.startsWith("Windows")) { 59 // Drive (MountedOn) Available/Total 60 dfFormat = "([^\\s]+)\\s+\\(([^\\s]+)\\)\\s+(\\d+)\\/(\\d+)\\s+"; 61 } else { 62 throw new RuntimeException("unrecognized system:" 63 + " os.name == " + name); 64 } 65 } 66 private static Pattern dfPattern = Pattern.compile(dfFormat); 67 68 private static int fail = 0; 69 private static int pass = 0; 70 private static Throwable first; 71 72 static void pass() { 73 pass++; 74 } 75 76 static void fail(String p) { 77 if (first == null) 78 setFirst(p); 79 System.err.format("FAILED: %s%n", p); 80 fail++; 81 } 82 83 static void fail(String p, long exp, String cmp, long got) { 84 String s = String.format("'%s': %d %s %d", p, exp, cmp, got); 85 if (first == null) 86 setFirst(s); 87 System.err.format("FAILED: %s%n", s); 88 fail++; 89 } 90 91 private static void fail(String p, Class ex) { 92 String s = String.format("'%s': expected %s - FAILED%n", p, ex.getName()); 93 if (first == null) 94 setFirst(s); 95 System.err.format("FAILED: %s%n", s); 96 fail++; 97 } 98 99 private static void setFirst(String s) { 100 try { 101 throw new RuntimeException(s); 102 } catch (RuntimeException x) { 103 first = x; 104 } 105 } 106 107 private static class Space { 108 private static final long KSIZE = 1024; 109 private String name; 110 private long total; 111 private long free; 112 113 Space(String total, String free, String name) { 114 try { 115 this.total = Long.valueOf(total) * KSIZE; 116 this.free = Long.valueOf(free) * KSIZE; 117 } catch (NumberFormatException x) { 118 // the regex should have caught this 119 assert false; 120 } 121 this.name = name; 122 } 123 124 String name() { return name; } 125 long total() { return total; } 126 long free() { return free; } 127 boolean woomFree(long freeSpace) { 128 return ((freeSpace >= (free / 10)) && (freeSpace <= (free * 10))); 129 } 130 public String toString() { 131 return String.format("%s (%d/%d)", name, free, total); 132 } 133 } 134 135 private static ArrayList space(String f) throws IOException { 136 ArrayList al = new ArrayList(); 137 138 Process p = null; 139 String cmd = "df -k" + (f == null ? "" : " " + f); 140 p = Runtime.getRuntime().exec(cmd); 141 BufferedReader in = new BufferedReader 142 (new InputStreamReader(p.getInputStream())); 143 String s; 144 int i = 0; 145 StringBuilder sb = new StringBuilder(); 146 while ((s = in.readLine()) != null) { 147 // skip header 148 if (i++ == 0 && !name.startsWith("Windows")) continue; 149 sb.append(s).append("\n"); 150 } 151 152 Matcher m = dfPattern.matcher(sb); 153 int j = 0; 154 while (j < sb.length()) { 155 if (m.find(j)) { 156 if (!name.startsWith("Windows")) { 157 // swap can change while this test is running 158 if (!m.group(1).equals("swap")) { 159 String name = (f == null ? m.group(4): f); 160 al.add(new Space(m.group(2), m.group(3), name));; 161 } 162 } else { 163 String name = (f == null ? m.group(2) : f); 164 al.add(new Space(m.group(4), m.group(3), name ));; 165 } 166 j = m.end() + 1; 167 } else { 168 throw new RuntimeException("unrecognized df output format: " 169 + "charAt(" + j + ") = '" 170 + sb.charAt(j) + "'"); 171 } 172 } 173 174 if (al.size() == 0) { 175 // df did not produce output 176 String name = (f == null ? "" : f); 177 al.add(new Space("0", "0", name)); 178 } 179 in.close(); 180 return al; 181 } 182 183 private static void tryCatch(Space s) { 184 out.format("%s:%n", s.name()); 185 File f = new File(s.name()); 186 SecurityManager sm = System.getSecurityManager(); 187 if (sm instanceof Deny) { 188 String fmt = " %14s: \"%s\" thrown as expected%n"; 189 try { 190 f.getTotalSpace(); 191 fail(s.name(), SecurityException.class); 192 } catch (SecurityException x) { 193 out.format(fmt, "getTotalSpace", x); 194 pass(); 195 } 196 try { 197 f.getFreeSpace(); 198 fail(s.name(), SecurityException.class); 199 } catch (SecurityException x) { 200 out.format(fmt, "getFreeSpace", x); 201 pass(); 202 } 203 try { 204 f.getUsableSpace(); 205 fail(s.name(), SecurityException.class); 206 } catch (SecurityException x) { 207 out.format(fmt, "getUsableSpace", x); 208 pass(); 209 } 210 } 211 } 212 213 private static void compare(Space s) { 214 File f = new File(s.name()); 215 long ts = f.getTotalSpace(); 216 long fs = f.getFreeSpace(); 217 long us = f.getUsableSpace(); 218 219 out.format("%s:%n", s.name()); 220 String fmt = " %-4s total= %12d free = %12d usable = %12d%n"; 221 out.format(fmt, "df", s.total(), 0, s.free()); 222 out.format(fmt, "getX", ts, fs, us); 223 224 // if the file system can dynamically change size, this check will fail 225 if (ts != s.total()) 226 fail(s.name(), s.total(), "!=", ts); 227 else 228 pass(); 229 230 // unix df returns statvfs.f_bavail 231 long tsp = (!name.startsWith("Windows") ? us : fs); 232 if (!s.woomFree(tsp)) 233 fail(s.name(), s.free(), "??", tsp); 234 else 235 pass(); 236 237 if (fs > s.total()) 238 fail(s.name(), s.total(), ">", fs); 239 else 240 pass(); 241 242 if (us > s.total()) 243 fail(s.name(), s.total(), ">", us); 244 else 245 pass(); 246 } 247 248 private static String FILE_PREFIX = "/getSpace."; 249 private static void compareZeroNonExist() { 250 File f; 251 while (true) { 252 f = new File(FILE_PREFIX + Math.random()); 253 if (f.exists()) 254 continue; 255 break; 256 } 257 258 long [] s = { f.getTotalSpace(), f.getFreeSpace(), f.getUsableSpace() }; 259 260 for (int i = 0; i < s.length; i++) { 261 if (s[i] != 0L) 262 fail(f.getName(), s[i], "!=", 0L); 263 else 264 pass(); 265 } 266 } 267 268 private static void compareZeroExist() { 269 try { 270 File f = File.createTempFile("tmp", null, new File(".")); 271 272 long [] s = { f.getTotalSpace(), f.getFreeSpace(), f.getUsableSpace() }; 273 274 for (int i = 0; i < s.length; i++) { 275 if (s[i] == 0L) 276 fail(f.getName(), s[i], "==", 0L); 277 else 278 pass(); 279 } 280 } catch (IOException x) { 281 fail("Couldn't create temp file for test"); 282 } 283 } 284 285 private static class Allow extends SecurityManager { 286 public void checkRead(String file) {} 287 public void checkPermission(Permission p) {} 288 public void checkPermission(Permission p, Object context) {} 289 } 290 291 private static class Deny extends SecurityManager { 292 public void checkPermission(Permission p) { 293 if (p.implies(new RuntimePermission("setSecurityManager")) 294 || p.implies(new RuntimePermission("getProtectionDomain"))) 295 return; 296 super.checkPermission(p); 297 } 298 299 public void checkPermission(Permission p, Object context) { 300 if (p.implies(new RuntimePermission("setSecurityManager")) 301 || p.implies(new RuntimePermission("getProtectionDomain"))) 302 return; 303 super.checkPermission(p, context); 304 } 305 } 306 307 private static class DenyFSA extends Deny { 308 private String err = "sorry - getFileSystemAttributes"; 309 310 public void checkPermission(Permission p) { 311 if (p.implies(new RuntimePermission("getFileSystemAttributes"))) 312 throw new SecurityException(err); 313 super.checkPermission(p); 314 } 315 316 public void checkPermission(Permission p, Object context) { 317 if (p.implies(new RuntimePermission("getFileSystemAttributes"))) 318 throw new SecurityException(err); 319 super.checkPermission(p, context); 320 } 321 } 322 323 private static class DenyRead extends Deny { 324 private String err = "sorry - checkRead()"; 325 326 public void checkRead(String file) { 327 throw new SecurityException(err); 328 } 329 } 330 331 private static void testFile(String dirName) { 332 out.format("--- Testing %s%n", dirName); 333 ArrayList l; 334 try { 335 l = space(dirName); 336 } catch (IOException x) { 337 throw new RuntimeException(dirName + " can't get file system information", x); 338 } 339 compare((GetXSpace.Space) l.get(0)); 340 } 341 342 private static void testDF() { 343 out.format("--- Testing df"); 344 // Find all of the partitions on the machine and verify that the size 345 // returned by "df" is equivalent to File.getXSpace() values. 346 ArrayList l; 347 try { 348 l = space(null); 349 } catch (IOException x) { 350 throw new RuntimeException("can't get file system information", x); 351 } 352 if (l.size() == 0) 353 throw new RuntimeException("no partitions?"); 354 355 for (int i = 0; i < sma.length; i++) { 356 System.setSecurityManager(sma[i]); 357 SecurityManager sm = System.getSecurityManager(); 358 if (sma[i] != null && sm == null) 359 throw new RuntimeException("Test configuration error " 360 + " - can't set security manager"); 361 362 out.format("%nSecurityManager = %s%n" , 363 (sm == null ? "null" : sm.getClass().getName())); 364 for (int j = 0; j < l.size(); j++) { 365 Space s = (GetXSpace.Space) l.get(j); 366 if (sm instanceof Deny) { 367 tryCatch(s); 368 } else { 369 compare(s); 370 compareZeroNonExist(); 371 compareZeroExist(); 372 } 373 } 374 } 375 } 376 377 public static void main(String [] args) { 378 if (args.length > 0) { 379 testFile(args[0]); 380 } else { 381 testDF(); 382 } 383 384 if (fail != 0) 385 throw new RuntimeException((fail + pass) + " tests: " 386 + fail + " failure(s), first", first); 387 else 388 out.format("all %d tests passed%n", fail + pass); 389 } 390 }