16

I created a directory d and a file f inside it. I then gave myself only read permissions on that directory. I understand this should mean I can list the files (e.g. here), but I can't.

will@wrmpb /p/t/permissions> ls -al
total 0
drwxr-xr-x   3 will  wheel  102  4 Oct 08:30 .
drwxrwxrwt  16 root  wheel  544  4 Oct 08:30 ..
dr--------   3 will  wheel  102  4 Oct 08:42 d
will@wrmpb /p/t/permissions> ls d
will@wrmpb /p/t/permissions>

If I change the permissions to write and execute, I can see the file.

will@wrmpb /p/t/permissions> chmod 500 d
will@wrmpb /p/t/permissions> ls d
f
will@wrmpb /p/t/permissions> 

Why is this? I am using MacOS.

Edit: with reference to @ccorn's answer, it's relevant that I'm using fish and type ls gives the following:

will@wrmpb /p/t/permissions> type ls
ls is a function with definition
function ls --description 'List contents of directory'
    command ls -G $argv
end
Stephen Kitt
  • 434,908
wrgrs
  • 967
  • The duplicate doesn't answer the question. It implies that you can do the thing that I demonstrate you can't. @ccorn's answer is perfect. – wrgrs Oct 04 '17 at 15:58
  • Wow, the Fish thing is a rather important piece of (initially) missing information. – Stephen Kitt Oct 04 '17 at 16:03
  • Yes you're right, I should have added it, but it looks like the same thing would happen in bash if you alias ls='ls -G', which I think many people do. – wrgrs Oct 04 '17 at 16:07
  • Does for me. Are you on MacOS? Maybe there's another question here. Edit: yep, I get different behaviour on Linux. – wrgrs Oct 04 '17 at 16:21

2 Answers2

12

Some preparations, just to make sure that ls does not try more things than it should:

$ unalias ls 2>/dev/null
$ unset -f ls
$ unset CLICOLOR

Demonstration of the r directory permission:

$ ls -ld d
dr--------  3 ccorn  ccorn  102  4 Okt 14:35 d
$ ls d
f
$ ls -l d
ls: f: Permission denied
$ ls -F d
ls: f: Permission denied

In traditional Unix filesystems, a directory was simply a list of (name, inode number) pairs. An inode number is an integer used as index into the filesystem's inode table where the rest of the file metadata is stored.

The r permission on a directory allows to list the names in it, but not to access the information stored in the inode table, that is, getting file type, file length, file permissions etc, or opening the file. For that you need the x permission on the directory.

This is why ls -l, ls -F, ls with color-coded output etc fail without x permission, whereas a mere ls succeeds.

The x permission alone allows inode access, that is, given an explicit name within that directory, x allows to look up its inode and access that directory entry's metadata:

$ chmod 100 d
$ ls -l d/f
-rw-r--r--  1 ccorn  ccorn  0  4 Okt 14:35 d/f
$ ls d
ls: d: Permission denied

Therefore, to open a file /a/b/c/f or list its metadata, the directories /, /a, /a/b, and /a/b/c must be granted x permission.

Unsurprisingly, creating directory entries needs both w and x permissions:

$ chmod 100 d
$ touch d/g
touch: d/g: Permission denied
$ chmod 200 d
$ touch d/g
touch: d/g: Permission denied
$ chmod 300 d
$ touch d/g
$

Wikipedia has a brief overview in an article on file system permissions.

ccorn
  • 236
  • Amazing. /bin/ls d shows the contents for me. Thanks! – wrgrs Oct 04 '17 at 15:55
  • OK, so it was a redefinition issue (with -G for colorized output, which needs metadata, thus x perms). Therefore my preparations with unalias ls and unset CLICOLOR. I should have added unset -f ls to remove any such function definition as well. Edited. – ccorn Oct 04 '17 at 16:51
  • More wiki ressources: https://wiki.archlinux.org/index.php/File_permissions_and_attributes – loxaxs Oct 28 '17 at 18:19
4

To read a directory you also need to be able to traverse into it (the x bit). So, at minimum you need r-x for a directory to be able to access it in any way.

Soruk
  • 251