Mac OS X Unleashed

Mac OS X Unleashed

By John Ray and William C. Ray

Introduction to File Permissions

This section expands on the topic of file permissions that was introduced in the section on the ls command. It's likely that you won't have an immediate use for modifying file permissions, and it's possible that you'll never need to deal with them at all. However, if you want to work with other users on the same system, or decide to start writing your own programs, understanding the permission system will be necessary.

Read, Write, and Execute

Permissions are specified as a collection of three flags. These flags (also called bits) control whether data in the file may be read, whether it may be written, and whether it may be executed. Unix takes these flags literally. So, if you have a program and you unset its execute flag, you won't be able to run the program—the system simply won't understand that the program is executable. Likewise, if you set the execute flag for a file containing a word processor document, Unix will assume that the file contents are a program and will try its best to run the file. This is unlikely to do anything but produce an error message.

In the case of directories, the same bits apply, but the meanings are slightly different. The read and write bits control whether the contents of the directory may be read, and whether the directory can be written to, respectively. The execute bit, however, controls whether the directory can be cded to, or otherwise moved into by a shell or program.

The permissions for whether a directory listing can be read or written to are separate from the permission that controls whether you, or programs, can move into it. Also, the permissions for files contained in the directory do not necessarily need to agree with the permissions of the directory. The significance of this might not be immediately apparent, but the meaning is quite literal. If you have files that have world read permission turned on, you can put them in a directory and set the bits on the directory so that the files in it can be read, but the files can't be listed. Likewise, you can set the permissions so that the directory allows anyone on the system to write files into it, but nobody can read the files or list the contents.

The execute permission for directories interacts with the read and write permission for files in it, in a slightly nonintuitive fashion. Read permission for the directory allows you to read the directory listing, but not the files. Read permission for a file in the directory allows you to read the file, but not list the directory. However, to be able to read the file, you, or rather the software you're using to read the file, need to be able to go into the directory. Because of this, if you turn on read permission for a directory and not execute permission, you can list the directory, but not read the files, no matter what the permissions on the files are. Likewise, you (or software under your control) can't write into a directory with only write permission turned on; execute permission must be enabled as well.

If you know that the file fizbin exists in the directory thozbot, but read and execute are turned off for thozbot, you can still read fizbin (assuming that you have read permission on fizbin itself) by using its full or relative path from outside the thozbot. If you don't know that fizbin exists in the directory, there's no way for you to find out, because you can't enter the directory or list the contents.

Owner, Group, and World

Adding a layer of complexity to the permission system, the read, write, and execute permissions detailed earlier can be specified separately for three subsets of users. They can be set for each owner of the file, the group owner of the file, and the world.

The owner of a file is, as the name implies, the user who owns the file. Each file on a Unix system has information stored about it that indicates to which user account the file belongs. Files that you create will automatically belong to your user ID. Other files on the system will belong to other users, or to one of the system accounts that exists to help the operating system keep its processes sorted out and secure.

Files have an additional piece of ownership information: the group ownership of the file. The group ownership specifies, by group name, a collection of users who share the group permissions to the file. This additional information facilitates the sharing of information among more than one user. Creating groups and controlling their membership were covered in Chapter 11, "Additional System Components."

Finally, there is a set of permission bits that control the access level enjoyed by the world, or at least all the other users on the system. If you provide any sort of guest access to your machine, it's best to assume that the file's world permissions do in fact apply to just about everyone, independent of location.

Extended Bits

In addition to the read, write, and execute bits for each file and directory, a few additional bits exist as well. These bits are typically used by system administrators, but they occasionally come in handy for other users.

The complete set of bits, including the extended bits, that control the permissions and properties of a file or directory are called the mode bits for the file.

Special Flags

Further extending the classical set of mode bits are a set of special flags. These are definitely not for use by anyone but the administrator, but are mentioned here because one particular bit can sneak up and bite you.

The most important of these for you to watch out for is the immutable flag. This flag is set by the Finder's locked status for a file. It's not currently clear why Apple chose this particular flag to map to the Finder's locked status, but it causes a few problems on the Unix side.

Checking the Permissions: ls -l

Remember that the ls -l command shows you the permissions associated with files. To find out the permissions associated with a single file, give it a filename to list:

[localhost:~] nermal% ls -l /etc/passwd

      -rw-r--r--  1 root  wheel  564 Feb 25 03:05 /etc/passwd

Controlling Permissions: chmod

After you are comfortable examining the permissions of files, you'll probably want to be able to change them. This is accomplished with the chmod (change mode) command. This command operates in either a "fully specified mode bits" manner, or in a "change this specific mode bit" manner, depending on the arguments you give it on the command line.

The "change this specific mode bit" form is the more friendly of the two, and works by allowing you to specify a bit to change, how to change it, and which type of user to change it for. The complete syntax for this form of the command is

chmod <u|g|o|a><+|-><r|w|x> <filename> ...

To use it, simply do the following:

  1. Pick whether you want to change the permissions for the user (yourself), the group, or the world. If you want to change the user, the first argument is u; g is for group; and o is for other (world).
  2. Pick whether you want to add or delete a permission. If you want to add a permission, follow your first argument with a + sign; otherwise, follow it with a - sign.
  3. Indicate the permission you want to add or delete using r for read, w for write, or x for execute. Follow these by the names of the files or directories for which you would like to change the permissions.

You might also use an a to indicate all, in place of the u, g, or o argument, if you want to make the change for the file to all three user types.

For example, consider a file named fizbin with the current permission set so that the user has full read, write, and execute permission, and the group and world have no permissions at all.

[localhost:~/Documents/test] nermal% ls -l

     total 0
     -rwx------  1 nermal  staff  0 Apr 22 23:32 fizbin

Perhaps this file is not actually a program, and to prevent yourself from accidentally trying to run it, you'd like to remove the execute permission from the user.

[localhost:~/Documents/test] nermal% chmod u-x fizbin
[localhost:~/Documents/test] nermal% ls -l

     total 0
     -rw-------  1 nermal  staff  0 Apr 22 23:32 fizbin

Now you would like to make it readable by both the group and the world.

[localhost:~/Documents/test] nermal% chmod g+r fizbin
[localhost:~/Documents/test] nermal% chmod o+r fizbin
[localhost:~/Documents/test] nermal% ls -l

     total 0
     -rw-r--r--  1 nermal  staff  0 Apr 22 23:32 fizbin

As you can see, this method of changing file permissions is fairly simple, but it does not lend itself to setting many permissions at once. More importantly, it changes the current permissions for the file one at a time. It can't set all the permission bits at once to force the file's mode bits into some particular pattern in a single command. To solve this, the chmod command also includes an "all at once" option, whereby you can specify the full complement of mode bits simultaneously.

This form of the command is slightly more complicated because it requires you to do a little math. In this form, the chmod command considers the mode bits for the file to be binary bits. To use the command, you need to specify which bits to set and which to unset.

Unfortunately, you can't do this in a manner as nice as just giving chmod a set of nine rwxrwxrwx characters, or ones and zeros. Instead, you must break up the nine bits of the mode bit set into three sets of three bits (rwx rwx rwx), and calculate the decimal equivalent of the bits that you want set.

Put another way, you could think of the elements in rwx as specifying where, in a binary string, a 1 occurs. This is done as shown here:

100 - read permission.    100 in binary = 4 in decimal.
010 - write permission.   010 in binary = 2 in decimal.
001 - execute permission. 001 in binary = 1 in decimal.

To find the decimal value equivalent of a particular combination of r, w, and x bits, you sum the decimal values that correspond to the bit patterns that represent them. So, if you wanted read and execute permission, with no write permission, you'd add 4 + 1 = 5, and for user, group, or world, would put a 5 in the pattern where needed.

A full example should help to explain this. Let's again consider the fizbin file, which, due to the use of chmod previously, has mode bits of rw-r--r--. That is to say, the user can read and write, and both the group and world can read. If you wanted to change this to mode bits r-xr-x--x, the syntax shown for the friendlier mode of chmod would require several commands. Instead, you could make this change in a single command by using the "all at once" form. To do so, follow these steps:

  1. Split the desired permissions into user, group, and world bits. This results in r-x belonging to the user, r-x belonging to the group, and --x belonging to the world.
  2. Calculate the decimal values for each: r-x is read permission and execute permission, which is 4+1 = 5. r-x for the group is the same. --x for the world is execute permission alone, which is simply 1.
  3. Put these together with the chmod command and the filename to change the mode bits for the file. In this case, chmod 551 fizbin.

Let's see whether it works:

[localhost:~/Documents/test] nermal% ls -l

     total 0
     -rw-r--r--  1 nermal  staff  0 Apr 22 23:32 fizbin
[localhost:~/Documents/test] nermal% chmod 551 fizbin
[localhost:~/Documents/test] nermal% ls -l

     total 0
     -r-xr-x--x  1 nermal  staff  0 Apr 22 23:32 fizbin

The command documentation table for chmod is shown in Table 14.1.

Table 14.1. The Command Documentation Table for chmod

Chmod Changes file modes
chmod [-R [-H | -L | -P]] [-h] <absolute_mode><file1> 
               <file2> ...

chmod [-R [-H | -L | -P]] [-h] <symbolic_mode><file1> 
               <file2> ...
-R Recursively descends through directory arguments to change file modes.
-H If -R is specified, symbolic links on the command line are followed. Symbolic links encountered in tree traversal are not followed.
-L If -R is specified, all symbolic links are followed.
-P If -R is specified, no symbolic links are followed.
Unless -H or -L is specified, chmod on a symbolic link always succeeds and has no effect. The -H, -L, and -P options are ignored unless -R is specified. Furthermore, -H, -L, and -P override each other. The last option specified determines the action that is taken.
Permissions are described by three sequences of letters in the order listed here. Each sequence describes the permissions for user, group, and other. If a certain permission has not been granted, a - (dash) appears in its place.


User    Group     Other

rwx     rwx      rwx
The permissions on a file can be viewed using ls -l and changed using chmod.
Absolute mode
Absolute mode is constructed by ORing any of the following modes:
4000 Sets user ID on execution
2000 Sets group ID on execution
1000 Turns on sticky bit
0400 Allows read by owner
0200 Allows write by owner
0100 Allows execute (search in a directory) by owner
0600 Allows read, write by owner
0500 Allows read, execute by owner
0300 Allows write, execute by owner
0700 Allows read, write, execute by owner
0040 Allows read by group
0020 Allows write by group
0010 Allows execute (search in a directory) by group
0060 Allows read, write by group
0050 Allows read, execute by group
0030 Allows write, execute by group
0070 Allows read, write, execute by group
0004 Allows read by other
0002 Allows write by other
0001 Allows execute (search in a directory) by other
0006 Allows read, write by other
0005 Allows read, execute by other
0003 Allows write, execute by other
0007 Allows read, write, execute by other
Symbolic mode
Symbolic mode is a comma-separated list, with no intervening white space, of the form:
[ <who> ] <operator> [ <permissions> ]
<who> has the following form:
< u | g | o | a>
U User's permissions
G Group's permissions
O Other's permissions
A All permissions (user, group, other); equivalent to ugo
<operator> has the following form:

< + | - | =>

+ Adds <permissions>.
If <permissions> is not specified, no changes occur.
If <who> is not specified, <who> defaults to a, and <permissions> are added as specified, except that chmod does not override the file mode creation mask.
If <who> is specified, <permissions> are added as specified.
- Removes <permissions>.
If <permissions> is not specified, no changes occur.
If <who> is not specified, <who> defaults to a, and <permissions> are removed as specified, except that chmod does not override the file mode creation mask.
If <who> is specified, <permissions> are removed as specified.
= Assigns the absolute <permissions> specified.
If <who> is not specified, <who> defaults to a.
If <permissions> is not specified, <permissions> defaults to remove.
If <who> is specified and <permissions> is not, all permissions for <who> are removed.
If <who> is not specified and <permissions> is specified, <permissions> for all are set to <permissions> , except that chmod does not override the file creation mask.
If <who> is specified and <permissions> is specified, <permissions> for <who> are set as specified.
<permissions> has the following form:
<r | w | x | X | s | t | u | g | o>
R Sets read bits.
W Sets write bits.
X Sets execute/search bits.
X Sets execute/search bits if the file is a directory, or if any execution/search bits are already set in the file before X would act upon the file. X is used only with +, and is ignored in all other cases.
s Sets the set-user-ID-on-execution and set-group-ID-on-execution bits. A process runs as the user or group specified by s.
t Sets the sticky bit.
u User permission bit in the mode of the original file.
g Group permission bits in the mode of the original file.
o Other permission bits in the mode of the original file.
Operations on <who> o in combination with <permissions> s or t are ignored.

Controlling a File's Group Ownership: newgrp, chgrp

As covered in Chapter 11, a user may belong to multiple different groups. Each of those groups may have different purposes on the system. For example, allowing groups of individual users to collaborate on projects, and allowing some users to belong to multiple different project groups.

A user who is a member of a group can access files that have that group as their group owner. As with real-life groups of people, however, each user can be in only one group at a time, no matter how many groups that user is a member of.

The group you are currently in is your effective group ID, and any files that you create while in this group will have the group ownership set to this group ID. If you are a member of multiple groups, you can pick the group ID that you are currently in by the use of the newgrp command. Issuing newgrp <groupname> switches your current group to <groupname> .

In addition to being created as belonging to the user's current group ID, group ownership of a file can be further controlled by the file's owner. The owner of a file has the ability to change the group ownership of a file to any group to which the owner belongs. Issuing chgrp <grou p name> <filename> will switch the group ownership of <filename> to <grou p name> , assuming that you are a member of <groupname> . The command documentation table for chgrp is shown in Table 14.2.

Table 14.2. The Command Documentation Table for chgrp

chgrp Changes group.
chgrp [-R [-H | -L | -P]] [-fh] <group> <file1> <file2> ...
-R Recursively descends through directory arguments to change the group ID.
-H If -R is specified, symbolic links on the command line are followed. Symbolic links encountered in tree traversal are not followed.
-L If -R is specified, all symbolic links are followed.
-P If -R is specified, no symbolic links are followed.
-f Forces an attempt to change group ID without reporting any errors.
-h If the file is a symbolic link, the group ID of the link is changed.
Unless -h, -H, or -L is specified, chgrp on symbolic links always succeeds and has no effect.
The -H, -L, and -P options are ignored unless -R is specified. Because they also override each other, the last one specified determines the action that is taken.
The group may be either a numeric group ID or a group name. If a group name exists for a group ID, the associated group name is used for the group.
The user invoking chgrp must belong to the specified group and be the owner of the file, or be the super user.
Unless invoked by the super user, chgrp clears the set-user-id and set-group-id bits.

Controlling the Special Flags

To modify the special flags, you use the chflags command. It's not at all clear what Apple is using the special flags for at the moment, although we do know that the Finder's locked status of a file sets the immutable bit on the Unix side. For example:

localhost testing 172> ls -l

     total 0
     -rw-r--r--  1 ray  staff  -   0 Jun 27 14:22 test
     -rw-r--r--  1 ray  staff  -   0 Jun 27 14:22 test2

localhost testing 173> su

     Password:

[localhost:/Users/ray/testing] root# chflags schg test
[localhost:/Users/ray/testing] root# ls -ol

     total 0
     -rw-r--r--  1 ray  staff  schg 0 Jun 27 14:22 test
     -rw-r--r--  1 ray  staff  -    0 Jun 27 14:22 test2

[localhost:/Users/ray/testing] root# chflags noschg test

     chflags: test: Operation not permitted

[localhost:/Users/ray/testing] root# rm test

     override rw-r--r--  ray/staff for test? y
     rm: test: Operation not permitted

The immutable flag is a relatively recent Unix invention, and indicates that the file cannot be changed. It's clear from the example that immutable really means just that: Even root can't delete the file, and what's more, root can't even remove the immutable flag after it has been set.

Even booting back into Mac OS 9.1 and trying to unlock the file from a Get Info dialog in the Finder turns out to be insufficient. The only successful route that we've found thus far is to remove the locked flag by the use of the venerable ResEdit program!

We don't really recommend experimenting with the chflags command much because it has the potential to make a real mess of things, and there's no documentation of what Apple is using the rest of the flags for. We've included the documentation table in Table 14.3, in case you should run across command examples using this in the future, as adventurous hackers pry the secrets out of OS X.

Table 14.3. The Command Documentation Table for chflags

chflags Changes file flags
chflags [-R [-H | -L | -P]] <flags> <file1> <file2> ...
-R Recursively descends through directory arguments to change file flags.
-H If -R is specified, symbolic links on the command line are followed. Symbolic links encountered in tree traversal are not followed.
-L If -R is specified, all symbolic links are followed.
-P If -R is specified, no symbolic links are followed.
Symbolic links do not have flags. Unless -H or -L is specified, chflags on a symbolic link always succeeds and has no effect. -H, -L, and -P options are ignored unless -R is specified. Furthermore, -H, -L, and -P override each other. The last option specified determines the action that is taken.
<flags> is a comma-separated list of keywords. Currently available keywords are as follows:
arch Sets the archived flag (super user only)
opaque Sets the opaque flag (owner or super user only)
nodump Sets the nodump flag (owner or super user only)
sappnd Sets the system append-only flag (super user only)
schg Sets the system immutable flag (super user only)
uappnd Sets the user append-only flag (owner or super user only)
uchg Sets the user immutable flag (owner or super-user only)
Prepending the letters no to a flag turns the flag off.

Share ThisShare This

Informit Network