All this time we have been talking about finding and executing commands, but
there is one issue that I haven’t mentioned. That is the concept of
permissions.
To access a file, you need to have permission to do so. If you want to read a
file, you need to have read permission. If you want to write to a file, you need
to have write permission. If you want to execute a file, it must have execute
permission.
Image – Various file types. (interactive)
For directories, the situation is slightly different than for regular files.
If you do not have read permission on a directory, you cannot read the contents
of that directory. Also, if you do not have write permission on a directory, you
cannot write to it. This means that you cannot create a new file in that directory.
Execute permissions
on a directory mean that you can search it or list its contents. That is, if the
execution bit is not set on a directory but the read bit is, you can see what
files are in the directory but cannot execute any of the files or even change
into that directory. If you have execution permission but no read permission,
you can execute the files, change directories, but not see what is in the
files.
Write permission on a directory also has an interesting side effect. Because
you need to have write permission on a directory to create a new file, you also
need to have write permission to remove an existing file. Even if you do not
have write permission on the file itself, if you can write to the directory, you
can erase the file.
At first this sounds odd. However, remember that a directory is nothing more
than a file in a special format. If you have write permission to a
directory-file, you can remove the references to other files, thereby removing
the files themselves.
If we were to set the permissions
for all users so that they could read, write, and execute a file, the command would look
this:
chmod 777 filename
You can also use symbolic permissions
to accomplish the same thing. We use the letters u, g, and o to specify the
user(owner), group, and others for this file, respectively. The
permissions are then r for read, w for write, and x for
execute. So to set the permissions so
that the owner can read and write a file, the command would look like this:
chmod u=rw filename
Note that in contrast to the absolute numbers, setting the permissions
symbolically is additive. So, in this example, we would just change the user’s permissions
to read and write, but the others would remain unchanged. If we changed the command to this
chmod u+w filename
we would be adding write permission for the user of that file. Again, the
permissions for the others would be unchanged.
To make the permissions for the group and others to be the same as for the user, we could set it like
this
chmod go=u filename
which simply means “change the mode so that the permissions
for the group and others equals the user.” We also could have set them all explicitly in
one command, like this
chmod u=rw,g=rw,o=rw filename
which has the effect of setting the permissions
for everyone to read and write. However, we don’t need to write that much.
Combining the commands, we could have something that looks like this:
chmod u=rw, go=u filename
This means “set the permissions
for the user to read and write, then set the permissions
for group and others to be equal to the user.”
Note that each of these changes is done in sequence. So be
careful what changes are made. For example, let’s assume we have a file that is
read-only for everyone. We want to give everyone write permission for it, so we
try
chmod u+w,gu=o filename
This is a typo because we meant to say
go=u. The effect is that we added read permissions
for the user, but then set the permissions on the group and user to the same as others.
We might want to try adding the write permissions
like this:
chmod +w filename
This works on some systems, but not some Linux distributions that I have
seen. According to the man-page,
this will not change those permissions where
the bits in the UMASK are set. (More on this later. See the chmod
man-page for details.)
To get around this, we use a to specify all users. Therefore,
the command would be
chmod a+w filename
There are a few other things that you can do with permissions.
For example, you can set a program to
change the UID
of the process when the program is executed. For example, some
programs need to run as root to access other files. Rather than giving the user
the root password, you can set the program so that when it is executed, the
process is run as root. This is a Set-UID, or SUID
program. If you want to run a
program with a particular group ID, you would use the SGID program with the s
option to chmod, like this
chmod u+s program
or
chmod g+s program
As in other cases, you can set permissions nurmerically, using the octal mode of the permissions. Since the SUID or SGID permissions are not part of the standard “rwx”, you need to add an extra digit, so you need four places. For SUID, you use the digit 4 and SGID you use 2. So, in the previous example, to make the file SUID, you might have this:
chmod 4755 program
There are a few other special cases, but I will leave it up to you to check out the chmod man-page
if you are interested.
When you create a file, the access permissions
are determined by their file creation mask. This is defined by the UMASK variable
and can be set using the umask command. One thing to keep in mind is that this
is a mask. That is, it masks out
permissions rather than assigning them. If you remember, permissions
on a file can be set using the chmod command and a three-digit value. For example
chmod 600 letter.john
explicitly sets the permissions
on the file letter.john to 600 (read and write permission for the user and nothing for
everyone else). If we create a new file, the permissions
might be 660 (read/write for user and group). This is determined by the UMASK. To understand
how the UMASK works, you need to remember that the permissions
are octal
values,
which are determined by the permissions
bits. Looking at one set of permissions
we have
| bit: | 2 | 1 | 0
|
| value: | 4 | 2 | 1
|
| symbol: | r | w | x
|
which means that if the bit with value 4 is set (bit 2), the file can be
read; if the bit with value 2 is set (bit 1), the file can be written to; and if
the bit with value 1 is set (bit 0), the file can be executed. If multiple bits
are set, their values are added together. For example, if bits 2 and 1 are set
(read/write), the value is 4+2=6. Just as in the example above, if all three are
set, we have 4+2+1=7. Because there are three sets of permissions
(owner, group, others), the permissions
are usually used in triplets, just as in the chmod
example above.
The UMASK value masks out the bits. The
permissions that each position in the UMASK masks out are the same as the file
permissions themselves. So, the left-most position masks out the owner
permission, the middle position the group, and the right most masks out all
others. If we have UMASK=007, the permissions
for owner and group are not
touched. However, for others, we have the value 7, which is obtained by setting
all bits. Because this is a mask,
all bits are unset. (The way I remember this
is that the bits are inverted. Where it is set in the UMASK, it will be unset in
the permissions, and vice versa.)
The problem many people have is that the umask
command does not force permissions,
but rather limits them. For example, if we had UMASK=007, we could assume
that any file created
has permissions
of 770. However, this depends on the program that is creating
the file. If the program is creating a file with permissions
777, the umask will
mask out the last bits and the permissions
will, in fact, be 770. However, if
the program creates permissions
of 666, the last bits are still masked out.
However, the new file will have permissions
of 660, not 770.
Some programs, like the C compiler, do generate files with the execution bit
(bit 0) set. However, most do not. Therefore, setting the UMASK=007 does not
force creation of executable programs, unless the program creating the file does
itself).
Lets look at a more complicated example. Assume we have
UMASK=047. If our program creates a file with permissions
777, then our UMASK
does nothing to the first digit, but masks out the 4 from the second digit,
giving us 3. Then, because the last digit of the UMASK is 7, this masks out
everything, so the permissions
here are 0. As a result, the permissions for the
file are 730. However, if the program creates the file with permissions
666, the
resulting permissions
are 620. The easy way to figure out the effects of the
UMASK are to subtract the UMASK from the default permissions
that the program
sets. (Note that all negative values become 0.)
As I mentioned, one way the UMASK is set is through the environment
variable UMASK. You can change it
anytime using the umask
command. The syntax is simply
umask <new_umask>
Here the <new_umask> can either be the numeric
value (e.g., 007) or symbolic. For example, to set the umask
to 047 using the symbolic notation, we have
umask u=,g=r,o=rwx
This has the effect of removing no permissions
from the user, removing read permission from the group, and removing all
permissions from others.
Being able to change the permissions on a file is often not enough. What if the
only person that should be able to change a file is not the owner? Simple! You
change the owner. This is accomplished with the chown command, which has the
general syntax:
chown new_owner filename
Where “new_owner” is the name of the user account we want to sent the owner of
the file to, and “filename” is the file we want to change. In addition, you
can use chown to change not only the owner, but the group of the file as well.
This has the general syntax:
chown new_owner.new:group filename
Another useful trick is the ability to set the owner and group to the same ones
as another file. This is done with the –reference= option, which sets to the
name of the file you are referencing. If you want to change just the group, you
can use the chgrp command, which has the same basic syntax as
chown. Not that both chgrp and chmod
can also take the –reference= option. Further, all three
of these commands take the -R option, which recursively changes the permissions,
owner or group.