8

The title pretty much says it, on Windows, can I somehow simulate multiple working directories in a multithreaded application by using something similar to openat?

See also this question.

18
  • 1
    Can't you just concatenate your relative path to a desired directory? Like: FILE* f = fopen("D:\\Temp\\folder2\\folder3\\..\\foo.h", "r"); Commented Aug 21, 2015 at 12:46
  • 1
    GetCurrentDirectory: "Each process has a single current directory [...]" Simulating multiple current working directories is not possible. But then, I don't see how that is helpful in implementing an openat equivalent, anyway. Could you update your question to be specific about what you really want? Commented Aug 21, 2015 at 13:01
  • 2
    No it would not. That's a hard limit. No way of escaping that one. Anyway, these comments aren't much fun because you seem to know more than we do, at least the way you are writing. In which case, I wish you all the best. You don't appear to need my help. Commented Aug 21, 2015 at 15:28
  • 3
    If you want to closely replicate the original openat call on Windows, you'll need to use _get_osfhandle to get a native file handle from a file descriptor, and GetFinalPathNameByHandle to retrieve the pathname. Concatenate the filename and open the file. Commented Aug 21, 2015 at 15:57
  • 3
    One of the important features is that your directory can be moved while open. And this is also a well known security problem. If your program is doing path concatenation but the sub path has been moved you could end up with file in very different places. If you think about it the current situation becomes insane, should never had implemented the way it is now. Commented Jul 4, 2019 at 9:53

1 Answer 1

15

Yes there is, and it's called NtCreateFile() (https://msdn.microsoft.com/en-us/library/bb432380(v=vs.85).aspx) :)

openat() takes an open fd to a base directory from which path operations start. Similarly, you can supply a HANDLE to the ObjectAttributes.RootDirectory of NtCreateFile() to have whatever that directory's path is to be used as a base for relative path operations.

If going direct to the NT kernel API is too much for you and you want to remain within Win32, you can retrieve the current path of the base directory HANDLE easily enough (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa366789(v=vs.85).aspx). If you open the directory without FILE_SHARE_DELETE permissions, nobody will be able to rename it and therefore the path retrieved will never move so long as you keep the HANDLE open.

You then stitch together the retrieved path with the relative path using normal string concatenation.

The NT kernel API approach is the only solution on Windows which allows the base directory HANDLE to be arbitrarily renamed by third party processes and that not cause races in your code. i.e. it's the only equivalent to POSIX openat(). I agree it's very unfortunate that Win32 doesn't make available this facility - in fact, Win32 doesn't make available atomic renames which is a very useful POSIX facility indeed to let you avoid lock files and is something the NT kernel API provides too.

Sign up to request clarification or add additional context in comments.

2 Comments

The NT kernel provides lots of stuff for the sake of its historical POSIX subsystem: en.wikipedia.org/wiki/Microsoft_POSIX_subsystem
Maybe it does, but without proper documentation and example codes who is going to use it. I still had no time to figure out NtCreateFile and that after 8 years where i could use it for good but still blocking other processes file actions. But MS can't even document shit on their brand new WinUI 3/Windows App SDK.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.