ziglang/zig

can't get errno when libc lstat returns -1

Closed this issue · 5 comments

Zig Version

0.9.1

Steps to Reproduce

const std = @import("std");
const c = @cImport({
    @cInclude("sys/stat.h");
});

pub fn main() anyerror!void {
    var stbuf: c.struct_stat = undefined;
    const ret = c.lstat("/no/exist/path", &stbuf);
    std.debug.print("ret = {}, c.errno = {}\n", .{ ret, std.c._errno().* });
}

Expected Behavior

The output should be: ret = -1, c.errno = 2.

Actual Behavior

But the actual output is ret = -1, c.errno = 0. The errno is not set correctly.

I’ve just stumbled upon this bug aswell when I was using Zig to compile C++ code on Linux. It works correctly with musl as the target, but is broken with glibc. I’m on Zig version 0.10.0-dev.2674+d980c6a38

I did some investigations on this issue and I think I found the culprit: zig has its own implementation of lstat here, so it has its own errno, but std.c._errno() gets external libc's errno which is different from it.

So this explains why we didn't get the correct errno when lstat.

This breaks using libgit2 with zig cc for me, since it relies on the lstat errno when creating the directory for cloning a repository (https://github.com/libgit2/libgit2/blob/1327dbcf2a4273a8ba6fd978db5f0882530af94d/src/util/futils.c#L527-L535)

This breaks using libgit2 with zig cc for me, since it relies on the lstat errno when creating the directory for cloning a repository (https://github.com/libgit2/libgit2/blob/1327dbcf2a4273a8ba6fd978db5f0882530af94d/src/util/futils.c#L527-L535)

Pretty sure I'm experiencing the same problem with sqlite which uses ltstat/errno to validate the path of a database to open.

This has been fixed. The given sample program passes (emits ret = -1, c.errno = 2) on a recent Zig (0.12.0-dev.3338+c85dd5c6d). Probably a dup of #17034 and fixed by the changes made for that in #17702.