8

I want to know whether the user launched our Java-based application from a read-only file system like from a .dmg, so functions like auto-update will be able to show meaningful information instead of aborting with an error. I first thought checking the .app's path would be sufficient (when launched from a .dmg it is something like /Volumes/MyApp 1.2.3/MyApp.app, but this won't work, because the user might have installed the application on a different partition. What other things may I check?

Mat
  • 202,337
  • 40
  • 393
  • 406
Thomas S.
  • 5,804
  • 5
  • 37
  • 72
  • What exactly is your definition of read-only? What if the filesystem is writable, but the user lacks permissions to modify the app bundle? Would that qualify? – NPE Dec 25 '14 at 10:18
  • No, because the application can request the permissions. – Thomas S. Dec 25 '14 at 12:37

3 Answers3

5

You can use -[NSURL getResourceValue:forKey:error:] with the key NSURLVolumeIsReadOnlyKey. You would apply this to the app bundle URL as returned by [[NSBundle mainBundle] bundleURL]. So:

NSBundle* bundle = [NSBundle mainBundle];
NSURL* bundleURL = bundle.bundleURL;
NSNumber* readOnly;
NSError* error;
if ([bundleURL getResourceValue:&readOnly forKey:NSURLVolumeIsReadOnlyKey error:&error])
{
    BOOL isReadOnly = [readOnly boolValue];
    // act on isReadOnly value
}
else
{
    // Handle error
}
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Could you please split into separate method calls, so it is easier for me to replicate from Java using SWT? Thanks in advance. – Thomas S. Dec 27 '14 at 12:04
3

If OSX is POSIX compliant, to determine if filesystem is mounted R/O, You can use statvfs() or fstatvfs(), returned struct statvfs field f_flag should have ST_RDONLY bit set for R/O filesystem.

As it was pointed in comments, check if this information is correctly provided by OS.

JNA and this question may be usefull for Java.

A few more ideas, which may be usefull here (access(), open(), utime() ).

OS X specific statfs() may be used too, but this function is not portable (Linux and *BSD have slightly different statfs() functions).

Community
  • 1
  • 1
kestasx
  • 1,091
  • 8
  • 15
  • Actually, being POSIX-compliant does **not** mean that one can use `statvfs()` to learn if a file system is read-only. The [man page](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/statvfs.3.html) says that POSIX doesn't actually require these functions to do *anything* and that they shouldn't be used by portable apps. Given that the question was specific to OS X, one could use them in this case, but your implication that one could use them on any POSIX-compliant OS isn't correct. – Ken Thomases Dec 25 '14 at 12:11
  • @KenThomases, http://pubs.opengroup.org/onlinepubs/9699919799/functions/statvfs.html says as of "Issue 7" these functions are moved to **Base** from **XSI**, so as I understand they are not optional anymore for POSIX conformat system. – kestasx Dec 25 '14 at 12:19
  • From your link "It is unspecified whether all members of the statvfs structure have meaningful values on all file systems". The functions are part of the Base standard, but are not required to **do anything**. – Ken Thomases Dec 25 '14 at 12:35
  • How to do that with Java? – Thomas S. Dec 25 '14 at 12:37
1

You can also check directly from Java whether a certain path points to something within a read-only directory by querying the FileStore associated with your path:

 File classpathRoot = new File(MyClass.class.getClassLoader().getResource("").getPath());
 /* getPath() actually returns a String instead of a Path object, 
  * so we need to take this little detour */
 Path yourAppPath = classpathRoot.toPath();
 boolean isReadOnly = Files.getFileStore(yourAppPath).isReadOnly();
Jan Gassen
  • 3,406
  • 2
  • 26
  • 44