Get CWD path without `realPath`

Getting started with Zig and trying to write a simple “print working directory” type of command. I’ve read the docs for std.Io.Dir and seen the realPath function and it’s siblings and the advice not to use it. Tried anyway and got an error.FileNotFound.

What is the idiomatic way to get a directory’s path as a string? Here’s the method I tried…

test "read file" {
    var base: [1024]u8 = undefined;
    const out_buffer: []u8 = base[0..];
    const io = std.testing.io;
    const cwd = std.Io.Dir.cwd();
    const path_length = try cwd.realPath(io, out_buffer);
    std.debug.print("CWD: {any} {any}", .{ out_buffer, path_length });
}

Any help appreciated.

Edit: I’m using Mac OS.

Hi, and welcome to Ziggit :slight_smile:
I know of std.process.currentPath(). It returns current working directory of the executed program.

6 Likes

I think you’re slightly misusing the function; maybe because cwd() is special on macOS? Anyway, this works:

const std = @import("std");

test {
    var base: [1024]u8 = undefined;
    const io = std.testing.io;
    const cwd: std.Io.Dir = .cwd();
    const pwd = try cwd.openFile(io, ".", .{});
    defer pwd.close(io);
    const len = try pwd.realPath(io, &base);
    std.debug.print("CWD: {s}", .{base[0..len]});
}
2 Likes

Be aware that realPath is not well supported across operating systems.

@lalinsky that was my original question. The docs mention the lack of OS support, but don’t offer an alternative means of getting a path from a File or Dir object, nor a way to test for OS support.

1 Like

You need to architecture your app so that you don’t need the path, or if you need it, you maintain it separately.

2 Likes

With the limitation that it thinks that you can’t have a longer path than MAX_PATH, which isn’t actually the case (at least on Unix-likes).

No, really, try it out. Here a small shell snippet which creates such a path and moves you inside of it:

for i in {1..10000}
do
    mkdir directory
    cd directory
done
pwd

But if you think about it, you CAN’T actually have a maximum path length.

And it’s very simple to explain why:
Let’s assume there is such a maximum length.

  1. Mount a disk under /mnt.
  2. Create a path which fully uses the maximum length up.
  3. Unmount the disk.
  4. Create another maximum path which uses the maximum path up fully or even just slightly less.
  5. Mount the disk again but now under that newly created path.
  6. You now have a path which is in total longer than the maximum path.

MAX_PATH is only actually used as the maximum length you can use in a single syscall (on Linux) for some syscalls but besides that is just an arbitrary value (and explicitly mentioned in Linux’ documentation to be arbitrary).

2 Likes