FileSpec::Resolve and (sym)links

Greetings,

I need to determine whether two filenames refer to the same file. The description on FileSpec::Resolve reads “Resolves user name and links in path, and overwrites the input
argument with the resolved path.”, which would seem to indicate that it already does symlink resolution. However, this is not the case.

My question is what is correct. Is it the comment (and then the function should be extended to do symlink resolution), or the implementation (and then we should change the comment to reflect that)?

I volunteer to do the work, but I am unsure what to do. Does anyone know what is the desired behavior?

regards,
pl

Please check llvm::sys::fs::equivalent () and see if that does what you want. If it doesn’t, think about whether your change could go there instead of LLDB

Thanks, that is exactly the function i was looking for.

However, I would still like to fix the inconsistency between the implementation and the comment of FileSpec::Resolve. Perhaps I should just rephrase the comment, since everyone seems to be happy with the current implementation?

pl

Jason once said that the behavior of Resolve used to be like that of realpath(), which does resolve links. So there may be some precedent to changing it.

The most sensible way to me would be to add llvm::sys::fs::real_path(). I’m not sure if ours used to just call straight through to realpath () though or if it had extra logic, so you’d want to check that. Also windows doesn’t have realpath(), so you’d need to implement it separately there (use CreateFile followed by GetFinalPathNameByHandle to resolve the symlink, plus whatever other logic is baked into realpath())

Yah I still have that small patch to Resolve in reviews.llvm.org to finish, I think it’s about done but haven’t had time to go back and commit yet. But that’s not relevant to Pavel’s issue, it was just another difference in behavior between realpath and the llvm method we’re using now.

The use of realpath, in addition to tilde expansion, was traditionally necessary in the debugger because we would think a solib was in /tmp, for instance, but on process launch the file path we get from our dynamic loader would have the /tmp → /private/tmp sym link on Darwin expanded. Running our /tmp path through realpath would get us the same pathname that the dynamic loader would use and we could match them up. Since then we’ve moved to identifying binaries based on their embedded UUIDs so strict path equivalence isn’t as important to us on Darwin today. But I can imagine other platforms needing this behavior of realpath.

If that’s the case that nobody is relying on realpath behavior for the moment, I would propose just fixing the comment, and later, when it’s needed, trying to add real_path() to llvmsupport

Just to provide a bit of context, I am investigating an issue where the debug symbols are not located in a splitdebug configuration. LLDB tries to locate the debug symbol file, but fails because it earlier on the search path it finds a symlink to the original file (which obviously does not provide any additional information). LLDB tries to skip over the same file <https://github.com/llvm-mirror/lldb/blob/master/source/Host/common/Symbols.cpp#L90>, but it does this by comparing filenames, which does not work in the presence of symlinks.

Now, having realpath() would solve this problem, but llvm::sys::fs::equivalent() is a more light-weight solution to this (and is readily available), so I think I’ll just call it. If you think realpath in general would be useful, then ok, otherwise I am fine with just fixing the comment.

Yea, I would rather wait on realpath. I talked to some people here who know more about it, and it’s apparently difficult to implement realpath in a way that is portable and gives the same semantics on all platforms. Even certain unix variants have slight differences in the semantics. It’s possible, just maybe not worth the time unless you really have a pressing need for it. So we can tackle it later when we actually need it.

Both with an without link resolve sounds useful. I think this should be controlled by a flag to Resolve. This will also prevent you from introducing any unintentional bugs.