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