Many disks have a sector size of 512 bytes, meaning that any read or write on the disk transfers a whole 512-byte sector at a time. It is quite natural to design filesystems where a sector is not split between files (that would complicate the design and hurt performance); therefore filesystems tend to use 512-byte chunks for files. Hence traditional utilities such as ls
and du
indicate sizes in units of 512-byte chunks.
For humans, 512-byte units are not very meaningful. 1kB is the same order of magnitude and a lot more meaningful. A filesystem block (the smallest unit that a file is divided in) actually often consists of several sectors: 1kB, 2kB and 4kB are common filesystem block sizes; so the 512-byte unit is not strongly justified by the filesystem design, and there is no good reason other than tradition to use a 512-byte unit outside a disk driver at all.
So you have a tradition that doesn't have a lot going for it, and a more readable convention that's taking on. A bit like octal and hexadecimal: there isn't one that's right and one that's wrong, they're different ways of writing the same numbers.
Many tools have an option to select display units: ls --block-size=512
for GNU ls
, setting POSIXLY_CORRECT=1
in the environment for GNU df
and GNU du
to get 512-byte units (or passing -k
to force 1kB units). What the stat
command in GNU coreutils exposes as the “block size” (the %B
value) is an OS-dependant value of an internal interface; depending on the OS, it may or may not be related to a size used by the filesystem or disk code (it usually isn't — see Difference between block size and cluster size). On Linux, the value is 512, regardless of what any underlying driver is doing. The value of %B
never matters, it's just a quirk that it exists at all.
Your answer lies in the first output you provided:
$ stat /home/jzhu/other
File: `/home/jzhu/other' -> `/root/other/'
This shows that /home/jzhu/other
is a symlink to /root/other
.
So basically to access anything in /home/jzhu/other/
you are going to need access to /root/other
. This means that your user must have execute permissions on both /root
and /root/other
.
Next lets go on to this command:
$ stat /home/jzhu/other/
stat: cannot stat `/home/jzhu/other/': Permission denied
The reason why this fails and the one above works is because of the trailing /
. On any command which works with a path, if the final component of that path (eg: other
) is a symlink, and the path ends with a trailing /
, then any system calls to operate on that path will try to dereference the symlink, and operate on what the symlink points to instead of the symlink itself.
Solutions:
There are 2 possible solutions to this.
1. Change permissions on /root/other
:
As mentioned, add execute capability to both /root
and /root/other
. You can do this with basic or extended filesystem attributes.
You can add the jzhu
user to the root
group (usermod -a -G root jzhu
) and add group execute to the path (chmod g+x /root; chmod g+x /root/other
).
This isn't an ideal solution as it grants your access to anything restricted to the root
group.
Use filesystem ACLs.
setfacl -m u:jzhu:x /root
setfacl -R -m u:jzhu:x /root/other
setfacl -d -R -m u:jzhu:x /root/other
This makes it so that your specific user gets execute access to /root/other
and anything inside it.
It's still not ideal as if these resources are shared, they shouldn't be in root's home directory.
Note that in both these solutions we only grant the execute (x
) bit. The execute bit is needed on a directory for a user to access anything inside that directory. However you also need the read (r
) bit to be able to list (ls
) the directory. Meaning that without the read bit, you'll have to know exactly where in /root/other
the files are. If you want to allow read, just change the x
in the last 2 setfacl
commands to rx
(for example, -m u:jzhu:rx
).
2. Move the resources outside /root/other
.
This is the preferred solution. You can either get rid of the symlink at /home/jzhu/other
and create a directory in it's place, or put them in a shared location somewhere else on the system (without knowing what it is, I can't recommend a good location though).
The reason this is the preferred solution is that if these resources are shared among users, then they don't belong to a specific user and shouldn't be in that user's home directory.
Best Answer
You can also use file test operators:
See here for more info about these operators: File test operators
But if you prefer to use
stat
you can divert its output to/dev/null
:Notice
./
in the commands above which means current directory. Also I should note that if you want to make stat completely silent (even in case of errors) divert errors to/dev/null
as well using&>/dev/null
or>/dev/null 2>&1
(have same result).