openat gives you the effect of 'cd path; open file' without having to cd. I don't see a lot of benefit to it unless you're opening a lot of files at that path. 

My first reaction, assuming you have a lot of files in that directory, was something like
bind /dir /n/x and then just open /n/x/file... for a lot of files. 

This would work for any system call that takes a path.

The question I had was, can I get the benefit of *at without doing what linux is doing, namely, for all system calls with a path, make an '...at' version.
I am guessing so, though I'm not sure it's as efficient.


On Fri, Apr 5, 2024 at 8:19 PM <moody@posixcafe.org> wrote:
My two cents on this:

What you _would_ want for this would be the ability to walk from the existing fd, however the limits of 9p walk make this a bit impossible to implement in a great way in my opinion. From walk(5):

The fid must represent a directory unless zero path name elements(for just cloning the fid) are specified. The fid must be valid in the current session and must not have been opened for I/O by an open or create message.

Since not every fid is eligible for being walked from, in order to implement opanat() in any way that would be better than just batching the fd2path and open would be to keep a "last directory" associated, like what we do with the string used to open it. Also worth mentioning that fd2path is not without its own problems, it's possible that the namespace has changed since the file has been opened so the same path may not work the second time. So tagging the last directory Chan would be "more correct", but I am not sure how useful this is.

Answering some other comments made:
As I understand it from the rationale section on the linux man page, the call exists to avoid a race condition between checking that a directory exists and doing something to a path containing it. An additional motivator is providing the effect of additional current working directories notably for Linux threads (which presumably don't have their own. I think 'threads'  (processes that share memory) on Plan 9 do???).

Each process has it's own current working directory:

% pwd
/home/moody
% @{cd /}
% pwd
% /home/moody

This is all based on the assumption that holding a file/directory open keeps it alive and in existence... which on Plan 9, I think it doesn't, does it? As I understand it, remove can remove a file or directory that is open, which is not like UNIX/Linux...


Depends on the file server implementation, I find that for more synthetic files they are indeed kept alive as long there is someone with a reference to the fid. This is identifiable if all the cleanup happens on clunks(destroyfid in lib9p), which only happen when a fid's refcount hits zero. For non-synthetic or more "disk" file servers the behavior can differ. Cwfs does not keep the data around, readers that attempt to read a deleted file, even if they already have a reference open to it will result in a phase error. However 9front's ramfs keeps the data around.

My test for this was as follows:
win1% echo 'something' >/tmp/test
win2% </tmp/test { sleep 10; cat }
win1% rm /tmp/test # observe the error(if any) on win2

So you really can't assume either case.


Thanks,
moody

P.S.
I apologize for the formatting, it seems my emails are not making it to the list when I attempt to send them from my mail server so I had to copy this response in to the web form.  I would like to figure out why if possible.