Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to create a file with world readable permission under subdirectory of files directory

I need to create files under myapp/files/subdir with global permission in my application. I do this because I use external applications to open some files Using this

 FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_WORLD_READABLE);

creates file only under files folder. Using

    File dir=new File(Constants.TASK_DIRECTORY);
    dir.mkdirs();
    File file=new File(dir, FILENAME);         
    file.createNewFile(); FileOutputStream fos=new FileOutputStream(file);

creates files under subdirectories but with private permissions. I need to find a way to compose those both to create a file in a subdirectory to be world readable

I have been trying a lot of things but none helped me and this was the longest time unanswered question of mine

like image 912
ikbal Avatar asked Oct 25 '11 08:10

ikbal


People also ask

How do I make a directory world readable?

To change directory permissions for everyone, use “u” for users, “g” for group, “o” for others, and “ugo” or “a” (for all). chmod ugo+rwx foldername to give read, write, and execute to everyone.

How do I give full permission to a folder and subfolders and files in Linux?

Use chmod -R 755 /opt/lampp/htdocs if you want to change permissions of all files and directories at once. Use find /opt/lampp/htdocs -type d -exec chmod 755 {} \; if the number of files you are using is very large.

How do I give permission to subdirectories in Unix?

To modify the permission flags on existing files and directories, use the chmod command ("change mode"). It can be used for individual files or it can be run recursively with the -R option to change permissions for all of the subdirectories and files within a directory.


3 Answers

I know this is an old question, but here is the correct way

public void makeFileWorldReadable(String path)
{
    File f = new File(path);

    if(!f.exists()) // Create the file if it does not exist.
        f.createNewFile();
    f.setReadable(true, false);
}
like image 155
Ne0 Avatar answered Oct 19 '22 02:10

Ne0


OP asked how to give access to a file in the following hierarchy: appdir/files/subdir/myfile.
The answers provided here don't take subfolder into account, so I feel there's a room for improvement.

In order to access file in hierarchy, a consumer should have execute permission on each folder in a path in order to access (read, write, execute) files underneath it.


For API >= 24

Starting from API 24, Android restricts access to appdir (a.k.a /data/data/appdir):

In order to improve the security of private files, the private directory of apps targeting Android 7.0 or higher has restricted access (0700). This setting prevents leakage of metadata of private files, such as their size or existence.

The appdir doesn't have world-execute permission, and therefore you can't cd into it:

angler:/ $ cd /data/data
angler:/data/data $ cd com.myapp
/system/bin/sh: cd: /data/data/com.myapp: Permission denied

Bottom line: you can give world-readable permission to one of the files in your app's folder, but no other app (as long as they don't share the same Linux user ID) will be able to read them.

Not only that: attempt to pass a file:// URI to external app will trigger a FileUriExposedException.


For API < 24

The appdir folder has world-execute permission by default:

shell:/ $ cd /data/data
shell:/data/data $ cd com.myapp
shell:/data/data/com.myapp $

Note that even the appdir/files folder has world-execute permission:

shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $ 

But if you'll try to create a sub-folder (underneath files folder), using this code:

File subdir = new File(context.getFilesDir(), "subfolder");
subdir.mkdir();

it won't have world-execute permission:

shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
/system/bin/sh: cd: /data/data/com.myapp/files/subfolder: Permission denied
shell:/data/data/com.myapp/files $ run-as com.myapp
shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $ ls -l 
total 72
drwx------ 3 u0_a226 u0_a226 4096 2016-11-06 11:49 subfolder
shell:/data/data/com.myapp/files $ 

Therefore, you have to explicitly give your newly created folder world-execute permission using File#setExecutable method (added in API 9):

subdir.setExecutable(true, false);

And only then, as suggested by others, you can create your file and give it world-readable permission:

File file = new File(subdir, "newfile");
if(!file.exists()) {
    file.createNewFile();
    file.setReadable(true, false);
}

Doing that will allow any external application read your file:

shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
shell:/data/data/com.myapp/files/subfolder $ cat newfile > /sdcard/1
shell:/data/data/com.myapp/files/subfolder $ cd /sdcard        
shell:/sdcard $ ls 1 
1
like image 32
Alex Lipov Avatar answered Oct 19 '22 03:10

Alex Lipov


If you are running it on a rooted device, change file permissions using:

Runtime.getRuntime().exec("chmod 777 " + PATH + fileName);

Or try File.setReadable(), File.setWritable while creating the file.

like image 6
JiTHiN Avatar answered Oct 19 '22 02:10

JiTHiN