Recipe 9.11 Working with Symbolic File Permissions Instead of Octal Values
9.11.1 Problem
You want to
print, inspect, or change permissions on a file or directory, but you
don't want to specify the permissions in octal (e.g.,
0644, 0755). You want to print
permissions as ls(1) shows them (e.g.,
-rwx-r-xr-x) and specify permissions changes in
the way that chmod(1) does (e.g.,
g-w to remove write access for the group).
9.11.2 Solution
Use the CPAN module Stat::lsMode to convert numeric permissions to a
string:
use Stat::lsMode;
$lsmode = file_mode($pathname);
Use the CPAN module File::chmod to manipulate symbolic permissions:
use File::chmod;
chmod("g=rw,o=-w", @files); # group can read/write, others can't write
chmod("-rwxr-xr--", @files); # ls-style permissions
9.11.3 Discussion
The Stat::lsMode module provides functions for generating
ls-style permissions strings. The
file_mode function takes a pathname and returns a
permissions string. This string is false if the pathname doesn't
exist or Perl can't stat it. If all goes well,
you get a string like "drwxr-x---" for a directory
or "-rwxr-x----" for a file. For more fine-grained
control, Stat::lsMode offers format_mode, which
takes a numeric permissions value and returns the 10-character
ls-style string.
Notice the leading d and - in
those strings. This indicates the type of file whose permissions
you're inspecting: - means regular file,
d means directory, l means
symbolic link, and so on. The format_perms
function from Stat::lsMode does the same job as
format_mode, but it returns a nine-character
string, which does not have the type indicator. For example:
use Stat::lsMode;
print file_mode("/etc"), "\n";
print format_mode((stat "/etc")[2]), "\n";
drwxr-xr-x
r-xr-xr-x
The File::chmod module gives you a chmod that
accepts these nine-character permissions strings:
use File::chmod;
chmod("rwxr-xr-x", @files);
These strings are three clusters of three characters. The three
clusters represent what the user, group, and others can do to the
file (respectively). The three characters represent
reading, writing, and
executing, with a dash (-) in
a column indicating the corresponding permission is denied to the
group. So in "rwxrw-r--", the owner can read,
write, and execute; users in the same group as the file can read and
write but not execute; and everyone else can only read.
You can specify relative changes to the permissions for a particular
file; for example, g-w removes write permission
from the group. The first letter(s) indicates whose permissions are
being changed (user, group,
other, or a combination). Then comes a
+ or - to indicate adding or
removing permissions, or = to indicate you're
specifying the complete set of permissions. Then you specify some or
all of rwx. You can join these with commas to form
relative permissions; for example, g-w,o+x (remove
write from group, add execute to other). If you omit the
u, g, or o,
then the change applies to everyone.
Here are some valid permissions changes and what they do:
u= remove all permissions for the user
g=r group can only read
g+wx group can also write and execute
g=rwx,o=rx group can do all, other can only read and execute
=rwx everybody can do everything
So you can now say:
chmod("u=", @files); # remove all permissions for the user on @files
chmod("g=r", @files);
chmod("g+wx", @files);
chmod("g=rwx,o-rx", @files);
chmod("=rwx", @files);
File::chmod also provides functions for seeing what the new
permission would be without actually making the change. See the
File::chmod documentation for more
details.
9.11.4 See Also
The documentation for the CPAN modules File::chmod and Stat::lsMode;
the chmod and stat functions in
perlfunc(1)
|