I have a project folder which has messy permissions on all files. I've had the bad tendency of setting everything to octal permissions 777 because it solved all non security related issues. Then FTP uploads, files created by text editors etc. has their own set of permissions making everything a mess. I've decided to take myself together and start using the permissions the way they were meant to be used.
I figured 664 was a good default for all my files and folders, and I'd just remove permissions for others on private files, and add +x for executable files.
The second I changed my project folder to 664 however:
$ sudo chmod -R 664 . $ ls ls: cannot open directory .: Permission denied
Which makes no sense to me. I have read/write permissions, and I'm the owner of the project folder. The leftmost part of ls -l in my project folder looks like this:
-rw-rw-r-- 1 codemonkey codemonkey ... drw-rw-r-- 5 codemonkey codemonkey ... -rw-rw-r-- 1 codemonkey codemonkey ... -rw-rw-r-- 1 codemonkey codemonkey ... drw-rw-r-- 3 codemonkey codemonkey ... -rw-rw-r-- 1 codemonkey codemonkey ... -rw-rw-r-- 1 codemonkey codemonkey ... -rw-rw-r-- 1 codemonkey codemonkey ... drw-rw-r-- 4 codemonkey codemonkey ... drw-rw-r-- 5 codemonkey codemonkey ...
I assume this has something to do with the permissions on the directories, but what?
2 Answers
The execute bit is needed to traverse a *nix directory. You can't cd into a directory that you don't have execute permissions for, and this affects a number of utilities in non-obvious ways if they need a directory context. Consider:
$ cd /tmp
$ mkdir foo
$ echo baz > foo/bar
$ chmod a-x foo
# You can read the contents of the directory, but ls still complains.
$ ls foo
ls: cannot access foo/bar: Permission denied
bar
# You can't read the file because you can't enter the directory.
$ cat foo/bar
cat: foo/bar: Permission deniedThe reason for all of this is the way that stat() works. Excerpted from man 2 stat:
No permissions are required on the file itself, but — in the case of stat() and lstat() — execute (search) permission is required on all of the directories in path that lead to the file.
The bottom line is that a recursive chmod will rarely do what you expect, and will play havoc with directory read and execute permissions that can lead to unexpected results like yours. Always treat directory permissions separately from file permissions for best results.
You need execute permissions on directories.
Consider
sudo find -type d -exec chmod +x {} +Update: heres my rationalisation of this, apparently odd, use of execute permissions.
Unix (and therefore Linux) pretty much treats everything as files. This extends to disks and to various other devices. it also includes directories.
Traditional Unix filesystems have a set of permissions that apply to files. Therefore the Unix desgners had to find something useful for each permission bit to do when applied to a "file" that wasn't your normal data file.
Let's consider directories. It initially seems reasonable to just use the read-permission to decide whether someone can access the directory - for example to produce a listing of the files in it and their sizes and datestamps etc.
However suppose you want ordinary users to be able to run programs in /usr/local/bin but you don't want them to be able to rummage around in /usr/local to see what's there. If you only have the read-permission you can't prevent this.
So the, otherwise redundant, execute permission was used to control whether your shell is allowed to "traverse" a directory, by which we mean, find out no more that is needed to be able to find and read the details of a subdirectory as part of a path. This allows you to get at the /usr/local directory only so far as is needed to read /usr/local/bin's contents.
So +x on /usr/local means you can run "/usr/local/bin/foo" But +r on /usr/local means you can find out everything that is in /usr/local including who owns it, what permissions each file has, what size it was etc.
The above is based on vague recollection and surmise. It may not be precisely true but I believe it gives a reasonable idea of why "execute" means "able to traverse".
6