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