CreateFile Permissions do not match mode parameter

Hi,
I’m new to zig, and I ran into a problem on my first attempt to write a program. I just wanted to know how to create and write to a file and was exploring the documentation of the standard library, when I encountered a problem.Hopefully you can help me.

Consider the following code snippet:

const std = @import("std");

pub fn main() !void {
    const permissions = 0o666;
    var file = try std.fs.cwd().createFile("sample.txt", .{ .mode = permissions }); 
    defer file.close();
}

When running this I get a file “sample.txt” but the permissions are:

-rw-rw-r-- 1 fuhl fuhl    0 Jul 11 20:32 sample.txt

which corresponds to 0o664 not 0o666 like I requested in the source.
No matter what I try the “world” write permissions are always omitted. If I leave out the parameter the default value should be applied. According to the stdlib the default value ist 0o666 which corresponds to “-rw-rw-rw-”, but I get “-rw-rw-r–”

Is this my fault, or is there a problem with the stdlib? Sorry if I missed something obvious.

Best,
SpinTensor

Btw.: I run the precompiled zig 0.12.0 x86_64 binary on Ubuntu 22.04.4 LTS

umask?

3 Likes

You can change permissions after creation

try file.chmod(permissions);

Thank you for your answers.
However, that does not solve the problem. I know how to change permissions. The problem is that the createFile function does not work as specified. There is a bug in the standard library that needs to be fixed.

I can reproduce the behavior locally, but it is not Zig-caused.

$ zig build-exe createfileperms.zig
$ strace ./createfileperms
openat(AT_FDCWD, "sample.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3

So 0666 is being passed to the openat syscall by Zig.

umask seems to be the answer.

$ umask
0002
$ umask 0
$ zig run createfileperms.zig
$ ls -la sample.txt
-rw-rw-rw- 1 ryan ryan 0 Jul 12 05:15 sample.txt
3 Likes

I opened an issue on github

Maybe it’s not a bug. In the source file std/fs/File.zig I see this:

/// This is the default mode given to POSIX operating systems for creating
/// files. `0o666` is "-rw-rw-rw-" which is counter-intuitive at first,
/// since most people would expect "-rw-r--r--", for example, when using
/// the `touch` command, which would correspond to `0o644`. However, POSIX
/// libc implementations use `0o666` inside `fopen` and then rely on the
/// process-scoped "umask" setting to adjust this number for file creation.
pub const default_mode = switch (builtin.os.tag) {
    .windows => 0,
    .wasi => 0,
    else => 0o666,
};

Hi

squeek502 is right

It’s not a bug. It’s your Operating System. Zig asks to create a file and your OS handles the request.

If you run umask in linux you get

umask
0022

Your 666 will become 644. ie 022 will be removed or Umasked.

This is why 777 would give you 755 if you tried it.

to set the Umask to 000 on your operating system try

umask 000

In full

umask 000

zig run main.zig

$ ls -l
-rw-rw-rw- 1 xxxxx xxxxx  0 Jul 15 12:34 sample.txt

$ umask
0000

Hope that make sense.

3 Likes