Contributor: Bastien Desert
Organization: OpenAFS
Mentor: Cheyenne Wills, Mark Vitale
Gerrit Change: venus: Add 'fs pathinfo' subcommand
Development Branch: fs-pathinfo
Timeline: May 25, 2026 - August 24, 2026
The subcommand is in src/venus/fs.c, with a -path argument taking a list of paths and a -verbose flag, defaulting to the current directory like the other path based subcommands. WalkPath() rebuilds the path component by component. name no entry of their own. DescribeEntry() handles one component, it calls lstat(), and for a directory sends a VIOC_AFS_STAT_MT_PT pioctl on the parent. If that succeeds the entry is a mount point and the volume name comes back in the output buffer, if it fails it is a plain directory.
% fs pathinfo -path /afs/example.com/usr/smith/joeSymlink/file '/afs' is a directory '/afs/example.com' is a mount point, for volume '#example.com:root.cell' '/afs/example.com/usr' is a mount point, for volume '#usr' '/afs/example.com/usr/smith' is a directory '/afs/example.com/usr/smith/joeSymlink' is a symbolic link, leading to '/afs/example.com/usr/joe' '/afs/example.com/usr/joe' is a mount point, for volume '#joe' '/afs/example.com/usr/joe/file' is a regular file
A relative path only describes the components that were named but with -verbose it is described from the top, and so is the path a symlink leads to. Several paths can be given, and a missing one stops that path without giving up the others. None of this needs AFS, on /tmp/foo/bar the command reports plain directories and files, since the mount point pioctl fails there. While reusing GetLastComponent() we also saw it splits the path with strdup() without checking the result, so on an allocation failure the strcmp() below dereferences NULL and fs segfaults instead of printing an error. That went in its own commit.
The man page is in doc/man-pages/pod1/fs_pathinfo.pod.template, with examples for full paths, relative paths, a path outside AFS and -verbose, and is linked from fs.pod.template. Writing them was more useful than I thought. The cases I had not handled, like a path ending with .., came out while writing down what the output should be. Getting a test cell running in a virtual machine took a good part of the first weeks, longer than planned. The command was then tested by hand on it, with volumes at several levels and symlinks made on purpose.
Both commits are pushed on Gerrit and under review, nothing is merged in master yet, and the GitHub branch above has the same work.
One thing is still not solved. /afs itself is reported as a directory, while it should be described as a mount point like the others. A solution for it still has to be designed. We talked about doing it with a pioctl, but we are not sure yet that this is the best idea, and it is the only thing left on the command.
I lost a lot of time on the build itself. I run NixOS, and compiling OpenAFS there gave me link errors that I never managed to get to the end of. I tried for a while, then gave up on building it natively and moved everything to a virtual machine, which is also where the test cell ended up running.
The codebase came first. fs.c is around four thousand lines by itself, and I had to understand how the cmd library registers a subcommand and how a pioctl reaches the kernel before writing much. Then the symlinks, where almost all of my bugs were. Targets resolved against the wrong directory, a target made only of .., links to links. My first version was one big function with fixed buffers on the stack, and moving them to the heap and cutting it in three did more for the bugs than any single fix.
Thank you to Cheyenne Wills for the weekly meetings, the reviews and the patience, in particular on the points I had to be told more than once. Thank you also to the OpenAFS community for the reviews on Gerrit, and to the organization administrators for making this summer possible.
This whole summer has been a really grateful experience for me. I learned much more than I expected, not only about AFS and about C, but also about how a project of this age is maintained and how people work together on it, review each other and keep a codebase alive for decades. This was my first contribution to a project of this size, and I hope to continue.