148

In Java, I'm dynamically creating a set of files and I'd like to change the file permissions on these files on a linux/unix file system. I'd like to be able to execute the Java equivalent of chmod. Is that possible Java 5? If so, how?

I know in Java 6 the File object has setReadable()/setWritable() methods. I also know I could make a system call to do this, but I'd like to avoid that if possible.

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
Roy Rico
  • 3,683
  • 6
  • 35
  • 36
  • 8
    Note for others: For existing files, since Java 7, you can use this one-liner: `Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxr-x---"))` – tom May 15 '19 at 08:09

12 Answers12

131

Full control over file attributes is available in Java 7, as part of the "new" New IO facility (NIO.2). For example, POSIX permissions can be set on an existing file with setPosixFilePermissions(), or atomically at file creation with methods like createFile() or newByteChannel().

You can create a set of permissions using EnumSet.of(), but the helper method PosixFilePermissions.fromString() will uses a conventional format that will be more readable to many developers. For APIs that accept a FileAttribute, you can wrap the set of permissions with with PosixFilePermissions.asFileAttribute().

Set<PosixFilePermission> ownerWritable = PosixFilePermissions.fromString("rw-r--r--");
FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(ownerWritable);
Files.createFile(path, permissions);

In earlier versions of Java, using native code of your own, or exec-ing command-line utilities are common approaches.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • 4
    selecting this one as I don't have the ability to use Marty Lamb's answer. – Roy Rico Mar 20 '09 at 00:44
  • 1
    I seriously cannot believe that it's been over six years since they started working on NIO.2 and it's still not in a shipping JRE. – clee Feb 03 '10 at 07:49
  • Yes, it's been a long time in coming. – erickson Feb 03 '10 at 16:13
  • 11
    Code example might be useful in your answer. – Ricardo Gladwell Sep 16 '13 at 16:00
  • Possible disadvantages of setPosixFilePermissions(): It cannot be used to set the setuid, setgid or sticky bits. It does not support numeric file modes, only String ones, although one could always write one's own conversion code. The JNA-based solution given by Marty Lamb below has neither of these disadvantages. – Simon Kissane Oct 14 '13 at 03:28
  • 3
    This answer http://stackoverflow.com/a/32331442/290182 by @PixelsTech is superior since it provides example code – beldaz May 30 '16 at 23:42
  • 1
    @SteveB All set. – erickson Jul 23 '18 at 16:37
50

Prior to Java 6, there is no support of file permission update at Java level. You have to implement your own native method or call Runtime.exec() to execute OS level command such as chmod.

Starting from Java 6, you can useFile.setReadable()/File.setWritable()/File.setExecutable() to set file permissions. But it doesn't simulate the POSIX file system which allows to set permission for different users. File.setXXX() only allows to set permission for owner and everyone else.

Starting from Java 7, POSIX file permission is introduced. You can set file permissions like what you have done on *nix systems. The syntax is :

File file = new File("file4.txt");
file.createNewFile();

Set<PosixFilePermission> perms = new HashSet<>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);

Files.setPosixFilePermissions(file.toPath(), perms);

This method can only be used on POSIX file system, this means you cannot call it on Windows system.

For details on file permission management, recommend you to read this post.

Patrick
  • 33,984
  • 10
  • 106
  • 126
PixelsTech
  • 3,229
  • 1
  • 33
  • 33
45

In addition to erickson's suggestions, there's also jna, which allows you to call native libraries without using jni. It's shockingly easy to use, and I've used it on a couple of projects with great success.

The only caveat is that it's slower than jni, so if you're doing this to a very large number of files that might be an issue for you.

(Editing to add example)

Here's a complete jna chmod example:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Main {
    private static CLibrary libc = (CLibrary) Native.loadLibrary("c", CLibrary.class);

    public static void main(String[] args) {
        libc.chmod("/path/to/file", 0755);
    }
}

interface CLibrary extends Library {
    public int chmod(String path, int mode);
}
Marty Lamb
  • 1,980
  • 1
  • 14
  • 10
  • 2
    JNA is such a nice tool for native calls! – erickson Mar 20 '09 at 04:32
  • 4
    For correct error handling, CLibrary.chmod() must be declared to throw com.sun.jna.LastErrorException. That is the only thread-safe way of getting the errno value set by the chmod() call. Otherwise, you can get the success/fail status from the return value, but not the actual error code. – Simon Kissane Oct 14 '13 at 03:23
22

For Windows 7 with NIO 2:

public static void main(String[] args) throws IOException {
    Path file = Paths.get("c:/touch.txt");
    AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
    System.out.println(aclAttr.getOwner());
    for (AclEntry aclEntry : aclAttr.getAcl()) {
        System.out.println(aclEntry);
    }
    System.out.println();
    
    UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
    UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
    AclEntry.Builder builder = AclEntry.newBuilder();       
    builder.setPermissions( EnumSet.of(AclEntryPermission.READ_DATA, AclEntryPermission.EXECUTE, 
            AclEntryPermission.READ_ACL, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_NAMED_ATTRS,
            AclEntryPermission.WRITE_ACL, AclEntryPermission.DELETE
    ));
    builder.setPrincipal(user);
    builder.setType(AclEntryType.ALLOW);
    aclAttr.setAcl(Collections.singletonList(builder.build()));
}
Lii
  • 11,553
  • 8
  • 64
  • 88
bob
  • 1,107
  • 10
  • 16
  • 2
    this works great. The only modification done was for the lookupPrincipalByName() method, I sent System.getProperty("user.name") instead of "user". Finally it looked like upls.lookupPrincipalByName(System.getProperty("user.name")); Thanks for the code! – isuru chathuranga Aug 06 '13 at 10:44
  • @bob.. can you give me AclFileAttributeView and UserPrincipalLookupService class.. bcz it cant resolve.. you answer seems to be working.. and i want to implement – Sagar Chavada Jul 08 '16 at 07:33
  • java.nio.file.attribute.AclFileAttributeView and java.nio.file.attribute.UserPrincipalLookupService, it require jdk 1.7+ to compile and run. – bob Jul 09 '16 at 16:50
  • I'm having the strangest result with this approach. I printed out the user, and it is my current active user. Yet I get access denied both in java, but also in windows when going to that file. I can't currently explain what is happening. – Kalec Aug 31 '21 at 14:27
13

Just to update this answer unless anyone comes across this later, since JDK 6 you can use

File file = new File('/directory/to/file');
file.setWritable(boolean);
file.setReadable(boolean);
file.setExecutable(boolean);

you can find the documentation on Oracle File(Java Platform SE 7). Bear in mind that these commands only work if the current working user has ownership or write access to that file. I am aware that OP wanted chmod type access for more intricate user configuration. these will set the option across the board for all users.

TravisF
  • 459
  • 6
  • 13
12

If you want to set 777 permission to your created file than you can use the following method:

public void setPermission(File file) throws IOException{
    Set<PosixFilePermission> perms = new HashSet<>();
    perms.add(PosixFilePermission.OWNER_READ);
    perms.add(PosixFilePermission.OWNER_WRITE);
    perms.add(PosixFilePermission.OWNER_EXECUTE);

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

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

    Files.setPosixFilePermissions(file.toPath(), perms);
}
MOTIVECODEX
  • 2,624
  • 14
  • 43
  • 78
2

Apache ant chmod (not very elegant, adding it for completeness) credit shared with @msorsky

    Chmod chmod = new Chmod();
    chmod.setProject(new Project());
    FileSet mySet = new FileSet();
    mySet.setDir(new File("/my/path"));
    mySet.setIncludes("**");
    chmod.addFileset(mySet);
    chmod.setPerm("+w");
    chmod.setType(new FileDirBoth());
    chmod.execute();
ihadanny
  • 4,377
  • 7
  • 45
  • 76
2
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

public class FileAndDirectory1 {
    public static void main(String[] args) {
        
        File file = new File("fileTest1.txt");
        System.out.println(file.getAbsoluteFile());
        try {
            //file.createNewFile();
            if(!file.exists())
            {
                //PosixFilePermission is an enum class, PosixFilePermissions is a final class
                
                //create file permissions from string
                Set<PosixFilePermission> filePermissions = PosixFilePermissions.fromString("---------"/* "rwxrwxrwx" */);
                FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(filePermissions);
                Files.createFile(file.toPath(), permissions);
                // printing the permissions associated with the file
                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.setExecutable(true);
                file.setReadable(true);
                file.setWritable(true);
            }
            else
            {
                //modify permissions
                
                //get the permission using file attributes
                Set<PosixFilePermission> perms = Files.readAttributes(file.toPath(), PosixFileAttributes.class).permissions();
                perms.remove(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);
                Files.setPosixFilePermissions(file.toPath(), perms);

                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Path path = Paths.get(String.valueOf(file));
        System.out.println(path);
    }
}
Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
2

You can use the methods of the File class: http://docs.oracle.com/javase/7/docs/api/java/io/File.html

davelupt
  • 1,845
  • 4
  • 21
  • 32
Erel Segal-Halevi
  • 33,955
  • 36
  • 114
  • 183
  • 4
    Please have a second look at the question. Roy Rico knows about setReadable() and setWritable(), but they only let you change owner permissions, not group or everyone permissions, or any of the other flags. – Chrissi Jan 05 '15 at 20:40
1

for Oralce Java 6:

private static int chmod(String filename, int mode) {
    try {
        Class<?> fspClass = Class.forName("java.util.prefs.FileSystemPreferences");
        Method chmodMethod = fspClass.getDeclaredMethod("chmod", String.class, Integer.TYPE);
        chmodMethod.setAccessible(true);
        return (Integer)chmodMethod.invoke(null, filename, mode);
    } catch (Throwable ex) {
        return -1;
    }
}

works under solaris/linux.

Vlad
  • 53
  • 1
  • 2
  • one should be aware that `FileSystemPreferences` spwans a `Timer` daemon thread once it's loaded. it also adds a shutdown hook, but for some applications this may still be problematic. – thrau Oct 16 '16 at 12:08
  • It's almost always a bad idea to call internal methods like this. – A248 May 29 '21 at 17:11
1

There is an example class on Oracle Docs which works very much similar to the UNIX chmod. It works with java se 7+ though.

jan.supol
  • 2,636
  • 1
  • 26
  • 31
1

Permission 777 is the same as rwxrwxrwx which you can set as follows:

Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxrwxrwx"))
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110