JDK-8230085 : (fs) FileStore::isReadOnly is always true on macOS Catalina
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7,8,11,14
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: os_x_10.15
  • CPU: x86
  • Submitted: 2019-08-20
  • Updated: 2022-06-27
  • Resolved: 2019-09-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13 JDK 14 JDK 7 JDK 8 Other
11.0.5Fixed 13.0.2Fixed 14 b15Fixed 7u251Fixed 8u231Fixed openjdk7uFixed
Related Reports
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
macOS Catalina (beta), OpenJDK 11.0.4 (but most likely this will affect any Java version)

A DESCRIPTION OF THE PROBLEM :
Beginning with macOS Catalina certain parts of the file system are write-protected.

However, `Files.getFileStore(anyPath)` doesn't distinguish protected and non-protected parts and will always return the same file store, which will then be reported as read-only.

The root path of a file system no longer defines whether the file system as a whole is read-only.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run attached test program on macOS Catalina.

Optionally change the path variable to any other existing path residing in non-protected regions.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Program prints "read-only: false"
ACTUAL -
Program prints "read-only: true"

---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Test {

	public static void main(String[] args) throws IOException {
		Path path = Paths.get("/tmp");
		System.out.println("read-only: " + Files.getFileStore(path).isReadOnly());
	}

}
---------- END SOURCE ----------

FREQUENCY : always



Comments
Ok, I agree. Just didn't want to take this decision alone. So, setting 11u-critical flag. Will push tomorrow before the final public tag.
23-09-2019

I think it makes sense to include this in 8u232, and I'd prefer to see 11.0.5 follow suit, but I'll leave that up to you. To me, this seems to be a low risk fix for a specific platform and makes the difference between OpenJDK being usable with Catalina on release (it's apparently also due in October 2019) or broken until next January. The only argument I see in the mailing list for not including it is that Oracle isn't, which doesn't seem like a sensible reason to me.
23-09-2019

That's correct. It doesn't seem as if Oracle will pull it into 11.0.5-oracle nor 8u232. We could take a different decision for OpenJDK updates, though. Maybe we should sync up between 8u and 11u? That is, either we push it to both, openjdk8u232 and 11.0.5 or defer it for both (openjdk8u242/11.0.6).
23-09-2019

Why was critical requested for 8u, but not 11u?
23-09-2019

Because of a specific request not to. [1] My understanding is it'll go into 11u tomorrow, targeted at 11.0.6 [2] [1] https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-September/001897.html [2] https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-September/001912.html
23-09-2019

Please note that all java.nio jtreg tests except for java/nio/Buffer are in tier 2, not tier 1. Before the JDK 14 patch was checked in, it was run through the CI system and passed tiers 1-3 on pre-Catalina nodes. The java/nio tests were run on a native Catalina system without problem.
17-09-2019

Fix Request I would like to request a backport of this fix to 8u, as without it isReadOnly() is broken on Catalina. I have tested this on a beta of Catalina, and also on High Sierra, and it does not change behaviour on High Sierra and fixes the issue on Catalina. The patch applies cleanly with only the usual path changes, and, on the Catalina beta. I have not rerun the tier1 tests, but did ensure that the test code now behaves in 8u as it did in jdk11u after applying the patch. Some discussion: https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-September/001879.html
17-09-2019

Fix Request I would like to request a backport of this fix to 11u, as without it isReadOnly() is broken on Catalina. I have tested this on a beta of Catalina, and also on High Sierra, and it does not change behaviour on High Sierra and fixes the issue on Catalina. The patch applies cleanly without changes, and, on the Catalina beta, passes jtreg:test/hotspot/jtreg:tier1 and jtreg:test/jdk:tier1 Some discussion: https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-September/001879.html
17-09-2019

URL: https://hg.openjdk.java.net/jdk/jdk/rev/3054503bad7d User: bpb Date: 2019-09-13 23:03:54 +0000
13-09-2019

Labelled noreg-other as this is convered by existing tests (regression and TCK).
13-09-2019

To fix this issue, the mount point found in step 2 of sun.nio.fs.BsdFileStore.findMountEntry() can instead be obtained from the f_mntonname member of the statfs structure initialized by the statfs(2) routine. This removes any dependence on the unreliable device id from stat.st_dev.
12-09-2019

Background information on the changes in the Apple File System (APFS) in macOS Catalina are discussed in [1]. The section pertinent to this issue is the first one, “Protecting system software on macOS.” Further information is available at [2]. In APFS a partition may contain one or more containers each of which has a separate storage region within the partition. Within each container there may be one or more volumes all of which have access to all the storage within their container. In Catalina the concept of a “Volume Group” is introduced. This is a conceptual grouping of volumes, not an actual structure. The macOS system volume in Catalina consists of a volume group composed of the read-only system volume and the data volume where users’ data resides. Isomorphic traversal points between the read-write data volume and the read-only system volume are implemented by a new file system object called a “firmlink.” A complete list of firmlinks is given in /usr/share/firmlinks. Each firmlink has one source and one target and cannot cross the boundary of a volume group. For example there is a firmlink between /Users and /Systems/Volumes/Data/Users. The path /System/Volumes/Data represents the data volume of the system volume group. Firmlinks are supposed to be transparent to users and applications. However some assumptions applications have made about inode numbers, file system IDs, and so on may no longer hold. This is the reason for the problem reported in the current issue. In sun.nio.fs.BsdFileStore.findMountEntry(), step 2, “find mount point,” relies on the device ID which is obtained from the st_dev field of the “struct stat” initialized by the stat(2) system call. This device ID does not change between the read-write data volume and the read-only system volume. Thus for example the device ID of /tmp (which is actually a symlink to /private/tmp) will be the same as that of root (/) so step 2 will go up the tree and identify “/“ as the file store for /tmp which is incorrect. [1] https://developer.apple.com/videos/play/wwdc2019/710/ [2] https://bombich.com/kb/ccc5/working-apfs-volume-groups
12-09-2019

We need access to a system with the current build of macOS Catalina. Supporting this release may require new development.
09-09-2019

On macOS, the JDK uses getfsstat to enumerate the mounted file systems and the mount flags will indicate if it is read-only or not. We need to examine a system with macOS Catalina to see if any changes are needed.
23-08-2019