I have a POSIX shared memory directory which gets blown away on reboot and needs to be recreated on occasion. An example,
#include <sys/stat.h> #include <sys/file.h> int main(int argc, char argv[]) { struct stat st = {0}; if (stat("/dev/shm/example", &st) == -1) { mkdir("/dev/shm/example", 0777); } }
This creates the directory with missing write permissions for group/others:
drwxr-xr-x. 2 *** *** *** May 14 12:00 example
I’ve tried experimenting with the mode_t flags and even replaced “0777” with “S_IRWXU | S_IRWXG | S_IRWXO”. I do need the directory to have permission flag 0777.
Advertisement
Answer
You need to set the permission explicitly or reset your file creation mask with the umask()
function.
Per the POSIX mkdir()
documentation (bolding mine):
The
mkdir()
function shall create a new directory with name path. The file permission bits of the new directory shall be initialized from mode. These file permission bits of the mode argument shall be modified by the process’ file creation mask.
The only thread-safe way to create a file or directory with the exact permissions you want is to explicitly set them after creation:
mkdir("/dev/shm/example", 0777); chmod("/dev/shm/example", 0777);
Of course, you’d do well to actually check the return values for those calls.
Calling umask()
to set and restore your file creation mask is not thread-safe:
mode_t old = umask( 0 ); mkdir("/dev/shm/example", 0777); umask( old );
There are multiple race conditions possible with doing that:
- The
old
mask you get with the first call toumask()
can be the0
set by another thread - Either call can overwrite the value of the file creation mask currently in use by another thread
If either of those race conditions happens, either
- your file/directory won’t get the permissions you need
- the other thread’s file/directory won’t get the permissions it needs
- the original file creation mask setting will be lost
Or all three.
So don’t call umask()
when you need to set permission bits exactly. Set the mode explicitly with a call to [f]chmod()
(The possible issues that could arise from creating directories in /dev/shm
is probably worth another question…)