7

I'm trying to create directory with public write permissions. To simplify things I want it to have 777 permissions. Here's my code:

private static FileAttribute<Set<PosixFilePermission>> DIR_PERMISSIONS;
static {
    Set<PosixFilePermission> perms = new HashSet<>();
    perms.add(PosixFilePermission.OWNER_WRITE);
    perms.add(PosixFilePermission.OWNER_READ);
    perms.add(PosixFilePermission.OWNER_EXECUTE);
    perms.add(PosixFilePermission.GROUP_WRITE);
    perms.add(PosixFilePermission.GROUP_READ);
    perms.add(PosixFilePermission.GROUP_EXECUTE);
    perms.add(PosixFilePermission.OTHERS_WRITE);
    perms.add(PosixFilePermission.OTHERS_READ);
    perms.add(PosixFilePermission.OTHERS_EXECUTE);
    DIR_PERMISSIONS = PosixFilePermissions.asFileAttribute(perms);
}

private Path ensurePath(LocalDate localDate) throws IOException {
    String year = String.valueOf(localDate.getYear());
    String month = String.format("%02d", localDate.getMonthValue());
    Path path = Paths.get(rootDirectory, year, month);
    return Files.createDirectories(path, DIR_PERMISSIONS);
}

With rootDirectory=/tmp/data this should create folders like /tmp/data/2016/01, each with 777 permissions. Instead folders have 775 permissions (drwxrwxr-x.) so they are lacking public write. Why is it working this way? Maybe JVM needs special param to be able to set such permissions? My system is Fedora 24, app is standard Spring Boot application, started by maven plugin.

xianoss
  • 141
  • 1
  • 10
  • 1
    @OlivierGrégoire It's not a duplicate because that does not explain *why* it's coming out as 775. – Michael Jan 26 '17 at 16:05
  • 1
    @Michael The main part of the question here is "I can't", not "why". The accepted answer in the other topic is complete as how to fix that. – Olivier Grégoire Jan 26 '17 at 16:13
  • @OlivierGrégoire "**Why** it's working this way?" – Michael Jan 26 '17 at 16:16
  • 2
    Is it possible the directory already existed? If it did, the new permissions would not be used by Files.createDirectories. – VGR Jan 26 '17 at 16:20
  • @Michael Thank you for the emphasis, but I can read, I assure you. If you read the whole question, the main component still is "how do I fix it?" despite the absence of those exact words. You may disagree, and you express it by not voting for close. I totally respect that. – Olivier Grégoire Jan 26 '17 at 16:20
  • 2
    What's the value of `umask` that your Java process is running under? It wouldn't be `002`, would it? – Andrew Henle Jan 26 '17 at 17:48
  • @OlivierGrégoire I would like to know solution how to fix it but also answer why it is happening. This is not duplicate since I know how to set permissions. I'm also far away from solution accepted there. My question is "why java sets chmod 775 when I'm telling it to set 777". – xianoss Jan 26 '17 at 18:32
  • @AndrewHenle I will check it tomorrow, but it's standard Spring Boot application (started by mvn spring-boot:run) – xianoss Jan 26 '17 at 18:32
  • @VGR I'm manually deleting this directories during tests, so answer is no. – xianoss Jan 26 '17 at 18:33
  • @Michael 'Why' is simply the existence of the *umask* facility, of course, which is rather trivial, and implied in the answer to the duplicate. – user207421 Jan 29 '17 at 20:54

1 Answers1

4

Okay well this got me curious so here goes:

Google led to this: https://stackoverflow.com/a/25557947/6768037 ("Java is setting the permission you seek and then it's being masked out.") which then leads back to the link that @OlivierGrégoire originally provided. umask is a harsh mistress.

Spring Boot has nothing to do with this behavior. Below is a simple proof of concept. My default umask is 0002. My /tmp directory is initially empty.

public class Test {
    public static void main(String[] args) {
        Set<PosixFilePermission> fullPermission = new HashSet<PosixFilePermission>();
        fullPermission.add(PosixFilePermission.OWNER_EXECUTE);
        fullPermission.add(PosixFilePermission.OWNER_READ);
        fullPermission.add(PosixFilePermission.OWNER_WRITE);

        fullPermission.add(PosixFilePermission.GROUP_EXECUTE);
        fullPermission.add(PosixFilePermission.GROUP_READ);
        fullPermission.add(PosixFilePermission.GROUP_WRITE);

        fullPermission.add(PosixFilePermission.OTHERS_EXECUTE);
        fullPermission.add(PosixFilePermission.OTHERS_READ);
        fullPermission.add(PosixFilePermission.OTHERS_WRITE);

        Path path = Paths.get("/tmp/data/", "01/26");
        try {
            Files.createDirectories(path, PosixFilePermissions.asFileAttribute(fullPermission));            
            outputLS(path);         
            Files.setPosixFilePermissions(path, fullPermission);            
            outputLS(path);         
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void outputLS(Path path) throws IOException {
        System.out.println(new java.util.Scanner(Runtime.getRuntime().exec("ls -alt " + path.toAbsolutePath() + "/..").getInputStream()).useDelimiter("\\A").next());
    }
}

Yields:

total 12
drwxrwxr-x 3 jsampson jsampson 4096 Jan 26 21:53 .
drwxrwxr-x 2 jsampson jsampson 4096 Jan 26 21:53 26
drwxrwxr-x 3 jsampson jsampson 4096 Jan 26 21:53 ..

total 12
drwxrwxr-x 3 jsampson jsampson 4096 Jan 26 21:53 .
drwxrwxrwx 2 jsampson jsampson 4096 Jan 26 21:53 26
drwxrwxr-x 3 jsampson jsampson 4096 Jan 26 21:53 ..

umask simply is in charge of all file/directory creation permissions. After creation it's possible to make changes.

Community
  • 1
  • 1
Jon Sampson
  • 1,268
  • 1
  • 16
  • 27