Saving and restoring current working directory

In zigbang, when it needs to compile the “script”, I tried to save and restore the current working directory, in between changing to the directory where to compile, using the following (with compile_dir being a Dir instance):

const old_wd = std.fs.cwd();
try compile_dir.setAsCwd();
.
.
old_wd.setAsCwd();

to my surprise this resulted in different behaviour between when the “script” needed compilation, and when not. This is because old_wd.setAsCwd(); is essentially a no-op, and old_wd.realpath() does change when compile_dir.setAsCwd(); is called.

Although I now seem to understand what is going on, I am not sure what is the best way to actually save and restore the current working directory. I don’t want to call realpath() as it may just disappear for the standard library.

For now I settled on

var outbuf: [1024]u8 = undefined;
var old_wd = try std.fs.openDirAbsolute(try std.posix.getcwd(&outbuf), .{});
defer old_wd.close();
try compile_dir.setAsCwd();
.
.
old_wd.setAsCwd();

and that works, but I would like to know if there is a better way to do this, that doesn’t involve getting a textual path representation first. E.g. using a saved inode+device of the current working directory, something which I thought the original code would do somehow.

The problem is that on a POSIX system std.fs.cwd() returns a special FDCWD file descriptor, which is a constant (-2) and always points to the current working directory, no matter what it is at any point in time.

I have not tested it, but perhaps doing something like this could be a good way to achieve what you want?

const old_wd = std.fs.cwd().openDir(".", .{});
defer old_wd.close();

This should open a brand new descriptor pointing to the current directory, frozen at that point in time, and should not be affected by changing the cwd in the future.

An interesting edge case, nevertheless!

1 Like

I had not thought about doing that, and your code almost works: OpenDir() returns an error union instead of “plain” Dir, and you cannot close old_wd (since it is a const).

const old_wd = try std.fs.cwd().openDir(".", .{});

will do it, without the full textual path and looks much better IMO.

Thanks.

1 Like

Ah, right, my bad!

You still probably should close old_wd (i.e. make old_wd a var and call close() on it), to avoid descriptor leaks. But yes, the rest makes a lot of sense :slight_smile:

I have no idea such descriptors are given back at the end of the program, so that seems the safer way to go