Using `statx` while avoiding `realpath`

Apologies if this is a bit incoherent or unnecessarily verbose, I started this from 0 a couple days ago and my head is spinning a little bit trying to sort out everything I’m learning, and filter out the parts where I confused myself :sweat_smile: tl;dr, I want to know if std.os.linux.statx follows symlinks, and if not, how do I get around using realpathfor the path argument of statx?

I have been looking at a moderately sized, ~15 year old C program and seeing how I might accomplish what it does in Zig as a fun learning project. At a particular part in this program, it does a few things:

  1. Uses realpath to get the path of a device file (so as to remove symlinks, which isn’t an uncommon occurrence for this program)
  2. Runs stat on the device file to confirm that it is either a character device or block device
  3. Gets the major ID from the rdev field of the stat, which will be switched upon later
  4. Opens the file, and runs ioctl (depending on the switch branch)

Most of these are not issues. My plan was to do the following:

  1. Open the file with std.fs.Dir.openFile, (from what I understand, this will follow symlinks, and so should be the actual device file?)
  2. Use std.os.linux.statxto get the rdev of the file, because it isn’t returned with a normal std.fs.Dir.stat
  3. Use std.fs.File.Stat.fromLinux()and inspect Stat.Kind to determine if it is a character/block device
  4. Use File.handle for ioctl

but the statx part isn’t so easy, as that requires the path to the device file, but we may have a symlink. Thus, my question: does statx follow symlinks? If not, I haven’t been able to work out a solution that doesn’t use realpath, but every discussion that includes realpath as a topic highly discourages its use, so I feel a bit stuck.

You can choose whether or not statx follows symlinks with a flag, but generally, you don’t need to do this, and shouldn’t do this. Same thing with realpath. Why not simply use the default flags and skip the realpath step? If you do that, what behavior do you get, and what behavior did you want instead?

1 Like

Might be missing something, but seems like open → fstat would work?

Or open → statx with the fd and an empty path if you need to specifically use statx. From the statx docs:

By file descriptor
     If path is an empty string (or NULL since Linux 6.11) and
     the AT_EMPTY_PATH flag is specified in flags (see below),
     then the target file is the one referred to by the file
     descriptor dirfd.

I was just trying to avoid stating the link itself, and not the device file the link points to. This is the first time I’ve looked at/tried writing a program that really works with the filesystem and hardware, so I’m not very familiar with it. I would have ideally just tried it and tinkered with what it outputs, but I was in a little too deep to switch gears to that (I am but a green hobby programmer)

I didn’t see the AT_EMPTY_PATH flag, that looks like exactly what I need, thank you!

1 Like