4

I have a windows cpp app and I want to resolve paths relative to a specific directory without changing the current directory. This means I can't use GetFullPathName since it resolves paths relative to the current directory. Since this is a security sensitive issue I would rather not roll my own but use a sanctioned API.

I looked around for a good answer, but couldn't find anything. Surely this is a common issue for web servers or multithreaded environments. How do other people do this? Any help would be greatly appreciated.

For instance: You run your app from C:\appfolder\exes\myapp.exe while the data is in C:\appfolder\data. I want to resolve sillyfolder\..\mydata.txt to C:\appfolder\data\mydata.txt.

JosiahDaniels
  • 2,411
  • 20
  • 37
  • Could you give an example? – Jim Rhodes Mar 09 '15 at 21:51
  • 1
    I don't think there is an API for this. I believe the usual approach would be to just append the two parts together (with a backslash, obviously) and leave the path in non-canonical form. If you know the file exists, I suppose you could open it and then call GetFinalPathNameByHandle. – Harry Johnston Mar 09 '15 at 22:46
  • @HarryJohnston, after concatenating the absolute base directory and the relative directory, why not call `GetFullPathName` to remove any `"."` and `".."` path components? `GetFinalPathNameByHandle` is useful if you need to resolve symbolic links in the full path, but you may have to iterate back to a path component that can be opened and then append the rest of the path that can't be accessed (either it doesn't exist or you have no access). – Eryk Sun Mar 10 '15 at 08:52
  • @eryksun: the documentation for `GetFullPathName` doesn't say what (if anything) it does if you pass it an absolute path. – Harry Johnston Mar 10 '15 at 18:59
  • @HarryJohnston, the docs are lacking, e.g. they don't discuss how `L"con"` becomes `L"\\\\.\\con"`, or using (and verifying) environment variables such as `"=D:"` for drive relative paths. ReactOS reverse engineers some of this in [`RtlGetFullPathName_UstrEx`](http://code.reactos.org/browse/~br=trunk/reactos/trunk/reactos/lib/rtl/path.c?r=65535#to1947) and [`RtlGetFullPathName_Ustr`](http://code.reactos.org/browse/~br=trunk/reactos/trunk/reactos/lib/rtl/path.c?r=65535#to468). FWIW, the documentation does give 3 examples: `\\test-2\q$\lh`, `\\?\UNC\test-2\q$\lh`, and `U:`. – Eryk Sun Mar 10 '15 at 20:35

1 Answers1

-1

The standard (C++ or Win32) libraries do not do this for you, it seems. But making a relative path is a good exercise. Here are a few useful links to see how to start (treat scripts as pseudocode):

Converting an absolute pathname to relative requires

  • the given target path which should be converted
  • a path which is the current directory.

The conversion would be done as a string-manipulation:

  • start by finding the longest common prefix which ends with a path-separator.
  • if there is no common prefix, you are done
  • strip the common prefix from (a copy of...) the current and target strings
  • replace each directory-name in the current string with ".."
  • add that (with a path-separator) in front of the target string
  • return that combined string

Unlike Unix pathnames (aside from the sense of "/" versus "\" for separators), Windows pathnames have additional complications:

  • within the same machine, they can have device names (a letter followed by a ":")
  • UNC pathnames, which begin with "\".

For the latter case (UNC paths), if the current and target paths are not on the same host, then relative paths are meaningless. However, device names and pathnames are not that tightly bound together (note that Windows added the ability to change devices with chdir later, as an option), and depending on the application one could make relative pathnames between devices by considering only the path part.

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • The OP wants to convert a relative path to an absolute path, not the other way around. – Harry Johnston Mar 10 '15 at 01:52
  • 1
    The first link should be useful then. The point is that there likely is no standard call, and that by looking at others' work, OP may learn how to do this. – Thomas Dickey Mar 10 '15 at 08:47