Filehandles, files, directories
umask#
Set or read the process file-creation mode mask.
umask controls which permission bits are cleared from the MODE
argument of every file- or directory-creation call made by this
process from now on. It is a property of the running process, not of
any particular filehandle, and it is inherited by child processes.
Call umask EXPR to install a new mask and receive the previous one;
call bare umask to read the current mask without changing it.
Synopsis#
umask EXPR
umask
What you get back#
The previous umask as an integer, so you can save it and restore it later:
my $old = umask 0077;
# ... create private files ...
umask $old;
Bare umask returns the current mask without changing it. If the
system has no umask(2)
call and the caller is trying to restrict access for itself
((EXPR & 0700) > 0), an exception is raised; if the call is not
implemented and the caller is not restricting its own access, undef
is returned. On Linux this case does not arise.
How the mask is applied#
The mask is subtractive. Every bit set in the umask is cleared
from the MODE passed to mkdir, sysopen,
open in creation modes, and the underlying
creat(2) /
mkdir(2)
system calls. The effective permissions of the new file are
MODE & ~umask.
A Unix permission like rwxr-x--- is three sets of three bits, or
three octal digits — 0750. The leading 0 marks the literal as
octal and is not itself a permission digit. A umask is written the
same way and names the bits you want disabled for newly created
files.
Worked example. With umask 0022, asking sysopen for
0666 actually creates a file with mode 0644:
0666 &~ 0022 = 0644
rw-rw-rw- ----w--w- rw-r--r--
With umask 0027 (group may not write, others may not read, write,
or execute), the same 0666 request yields 0640
(0666 & ~0027 == 0640).
Global state it touches#
The mask itself is process-global kernel state set via
umask(2).
umask does not read or write any Perl special variable directly,
but every creation call in the process observes it, and $!
is set by the underlying system calls that consume the mask
(mkdir, sysopen, open), not by
umask itself. Child processes spawned via fork,
exec, or system inherit the current value.
Examples#
Install a mask that hides the file from everyone but the owner, keeping the previous value for restoration:
my $old = umask 0077;
open my $fh, ">", "secret.txt" or die "open: $!";
# secret.txt is created mode 0666 & ~0077 == 0600
close $fh;
umask $old;
Read the current mask without changing it — useful for logging or diagnostics:
printf "current umask: %04o\n", umask; # e.g. "current umask: 0022"
Typical values to pass — these are the three masks actually used in practice:
umask 0022; # group + other: read/execute, no write (default on most systems)
umask 0027; # group: read/execute; other: nothing
umask 0077; # owner-only; nothing for group or other
Scoped change around a block of file-creating code. umask has no
local magic of its own — save and restore explicitly:
sub write_private_file {
my ($path, $data) = @_;
my $old = umask 0077;
open my $fh, ">", $path or do {
umask $old;
die "open $path: $!";
};
print $fh $data;
close $fh;
umask $old;
}
Octal literal vs. string — a common trap. A umask is a number,
not a string of octal digits. Reading one from configuration requires
oct:
my $from_config = "0027"; # string
umask oct $from_config; # correct: 0027 as a number
umask $from_config; # WRONG: decimal 27 == 033 octal
Edge cases#
Bare
umaskin list context still returns a single integer. The function is scalar-valued.Negative or out-of-range values are masked to the nine low-order permission bits by the kernel; only bits
0777survive. Passing0777disables all permissions on every newly created file, which is almost never what you want.umaskdoes not affect existing files. It only filters theMODEargument of creation calls. To change an existing file’s permissions usechmod.umaskdoes not affectopenfor an existing file — opening a file that already exists does not re-apply the mask. It applies only when a file is being created (O_CREATinsysopen, or>/>>/+>modes creating a new pathname inopen).Inheritance across
fork/exec. Children start with the parent’s current umask. Setting the mask beforesystemorexecchanges the environment the child inherits; restore it afterwards if the parent still cares.Threads. The umask is a per-process attribute in the kernel, so on systems where Perl threads share a process (the usual case) every thread sees the same mask. Changing it in one thread changes it for all.
umask(2)not implemented. The POD documents a fallback path for systems without the syscall: raise on attempts to restrict the owner’s own access, otherwise returnundef. Every platform pperl targets hasumask(2), so this path is effectively unreachable here.Octal presentation. Print the mask with
printf "%04o"; the default%dprints decimal, which is unreadable as permission bits.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
chmod— change permissions on an existing file; the counterpart to the creation-time filteringumaskperformsmkdir— directory creation call whoseMODEargument is filtered through the current umasksysopen— low-level file creation whoseMODEargument is filtered through the current umask; the canonical place where the mask is feltopen— in creation modes (>,>>,+>) the underlyingcreat(2)applies the umask to the default0666oct— convert a string like"0027"to the integer valueumaskexpects$!— set by the creation calls that consume the mask, not byumaskitself; check it after theopen/sysopen/mkdirthat fails