diff --git a/test/jdk/java/io/File/GetXSpace.java b/test/jdk/java/io/File/GetXSpace.java index d76000dbef5..512ea51780b 100644 --- a/test/jdk/java/io/File/GetXSpace.java +++ b/test/jdk/java/io/File/GetXSpace.java @@ -54,6 +54,8 @@ public class GetXSpace { System.loadLibrary("GetXSpace"); } + private static final Pattern DF_PATTERN = Pattern.compile("([^\\s]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+\\d+%\\s+([^\\s].*)\n"); + private static int fail = 0; private static int pass = 0; private static Throwable first; @@ -104,8 +106,17 @@ public class GetXSpace { Space(String name) { this.name = name; long[] sizes = new long[4]; - if (getSpace0(name, sizes)) - System.err.println("WARNING: total space is estimated"); + if (Platform.isWindows() & isCDDrive(name)) { + try { + getCDDriveSpace(name, sizes); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("can't get CDDrive sizes"); + } + } else { + if (getSpace0(name, sizes)) + System.err.println("WARNING: total space is estimated"); + } this.size = sizes[0]; this.total = sizes[1]; this.free = sizes[2]; @@ -167,7 +178,8 @@ public class GetXSpace { out.format("%s (%d):%n", s.name(), s.size()); String fmt = " %-4s total = %12d free = %12d usable = %12d%n"; - out.format(fmt, "getSpace0", s.total(), s.free(), s.available()); + String method = Platform.isWindows() & isCDDrive(s.name()) ? "getCDDriveSpace" : "getSpace0"; + out.format(fmt, method, s.total(), s.free(), s.available()); out.format(fmt, "getXSpace", ts, fs, us); // If the file system can dynamically change size, this check will fail. @@ -324,7 +336,7 @@ public class GetXSpace { private static int testVolumes() { out.println("--- Testing volumes"); // Find all of the partitions on the machine and verify that the sizes - // returned by File::getXSpace are equivalent to those from getSpace0 + // returned by File::getXSpace are equivalent to those from getSpace0 or getCDDriveSpace ArrayList l; try { l = paths(); @@ -397,4 +409,40 @@ public class GetXSpace { // size[3] usable space: number of bytes available to the caller // private static native boolean getSpace0(String root, long[] space); + + private static native boolean isCDDrive(String root); + + private static void getCDDriveSpace(String root, long[] sizes) + throws IOException { + String[] cmd = new String[] {"df", "-k", "-P", root}; + Process p = Runtime.getRuntime().exec(cmd); + StringBuilder sb = new StringBuilder(); + + try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) { + String s; + int i = 0; + while ((s = in.readLine()) != null) { + // skip header + if (i++ == 0) continue; + sb.append(s).append("\n"); + } + } + out.println(sb); + + Matcher m = DF_PATTERN.matcher(sb); + int j = 0; + while (j < sb.length()) { + if (m.find(j)) { + sizes[0] = Long.parseLong(m.group(2)) * 1024; + sizes[1] = Long.parseLong(m.group(3)) * 1024; + sizes[2] = sizes[0] - sizes[1]; + sizes[3] = Long.parseLong(m.group(4)) * 1024; + j = m.end(); + } else { + throw new RuntimeException("unrecognized df output format: " + + "charAt(" + j + ") = '" + + sb.charAt(j) + "'"); + } + } + } } diff --git a/test/jdk/java/io/File/libGetXSpace.c b/test/jdk/java/io/File/libGetXSpace.c index a4e36bd2431..c45aea14691 100644 --- a/test/jdk/java/io/File/libGetXSpace.c +++ b/test/jdk/java/io/File/libGetXSpace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,6 +159,33 @@ Java_GetXSpace_getSpace0 (*env)->SetLongArrayRegion(env, sizes, 0, 4, array); return totalSpaceIsEstimated; } + +JNIEXPORT jboolean JNICALL +Java_GetXSpace_isCDDrive + (JNIEnv *env, jclass cls, jstring root) +{ +#ifdef WINDOWS + const jchar* strchars = (*env)->GetStringChars(env, root, NULL); + if (strchars == NULL) { + JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException", + "GetStringChars"); + return JNI_FALSE; + } + + LPCWSTR path = (LPCWSTR)strchars; + UINT driveType = GetDriveTypeW(path); + + (*env)->ReleaseStringChars(env, root, strchars); + + if (driveType != DRIVE_CDROM) { + return JNI_FALSE; + } + + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} #ifdef __cplusplus } #endif