My code uses LoadLibraryA("someDLL.dll"); What is the path it starts searching for the file someDLL.dll?And another question : is LoadLibraryA function case-sensitive?I mean if I have SomeDLL.dll it will not load it?
The MSDN Library article Dynamic-Link Library Search Order specifies the search order for desktop applications when SafeDllSearchMode is enabled, which is the default starting with Windows XP SP2:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
LoadlLibrary article specifies search order in Remarks:
If lpFileName does not include a path and there is more than one
loaded module with the same base name and extension, the function
returns a handle to the module that was loaded first.
If no file name extension is specified in the lpFileName parameter,
the default library extension .dll is appended. However, the file name
string can include a trailing point character (.) to indicate that the
module name has no extension. When no path is specified, the function
searches for loaded modules whose base name matches the base name of
the module to be loaded. If the name matches, the load succeeds.
Otherwise, the function searches for the file. [...]
For more information on the DLL search order, see Dynamic-Link Library
Search Order.
File names are not case sensitive, so NTFS and FAT file names are. It is the fundamental rule to not assume case sensitivity:
Naming Conventions
The following fundamental rules enable applications to create and process valid names for files and directories, regardless of the file system: [...]
Do not assume case sensitivity.
Related
I have the feeling the C++ filesystem standard is broken on windows. It is heavily based on Boost.filesystem and I just found a serious issue there which (likely) also exists in std::filesystem: https://github.com/boostorg/filesystem/issues/99
The essence is the definition of "root_name" and "root_directory":
root-name(optional): identifies the root on a filesystem with multiple roots (such as "C:" or "//myserver"). In case of ambiguity, the longest sequence of characters that forms a valid root-name is treated as the root-name. The standard library may define additional root-names besides the ones understood by the OS API.
root-directory(optional): a directory separator that, if present, marks this path as absolute. If it is missing (and the first element other than the root name is a file name), then the path is relative and requires another path as the starting location to resolve to a file name.
This requires e.g. "C:\foo\bar.txt" to be decomposed into:
root_name: "C:"
root_directory: "\" or "/" (does this even make sense?)
directory: "foo"
file_name "bar.txt"
The problem now: The first part of this path is not a path, at least not the original one. This comes from the interpretation on windows:
"C:\" is the drive "C"
"C:" is the current working directory on the drive "C"
Minor: How should "\foo\bar.txt" be interpreted on windows according to the above? You have a "root_directory" (which is strangely not a directory but a directory separator) but no "root_name" hence the path cannot be absolute and so you don't have a "root_directory" either. sigh.
So from this I feel that "root_name" and "root_directory" cannot be decomposed (on windows). In "C:\foo" you'll have "C:\" and in "C:foo" you'll have "C:". Or to keep the (strangely defined) "root_directory" you'd need to set decompose "C:\foo" into "C:\", "\" and "foo" and struggle with the latter: Is that an absolute path? Actually it is: "The folder 'foo' in the current working directory on drive C", quite absolute, isn't it?
But well you could say "absolute==independent of current working dir" then the "root_directory" makes sense: It would be "\" for "C:\foo" and empty for "C:foo".
So question: Is the standard wrong in defining "C:" as the "root_name" instead of "C:\" in paths like "C:\foo" or is it simply invalid usage to iterate over components of a path expecting the prefix sums to be "valid"?
Your interpretation of the Windows filesystem is incorrect. The directory C:\ is the root directory of the "C" drive, not "the drive 'C'". This is distinct from C:, which is the current directory of the "C" drive. Just try using the Windows shell and see how C:<stuff> behaves relative to C:\<stuff>. Both will access stuff on that drive, but both will do so starting from different directories.
Think of it in these terms on Windows:
C: means "Go to the current directory of the C drive".
\ at the start of a path (after any root names) means "Go to the root directory of the current drive".
foo\ means "Go into the directory called 'foo' within whatever directory we are currently in".
bar.txt means "The file named 'bar.txt' in whatever directory we are currently in."
Therefore, C:\foo\bar.txt" means: Go to the current directory of the C drive, then go to the root directory of C, then go into the 'foo' directory of the root directory of C, then access the file 'bar.txt' in the 'foo' directory of the root directory of C.
Similarly, C:foo\bar.txt means: Go to the current directory of the C drive, then go into the 'foo' directory of the current directory of C, then access the file 'bar.txt' in the 'foo' directory of the current directory of C.
This is how Windows paths work. This is what it means to type those things in the Windows shell. And thus, this is how Boost/std filesystem paths were designed to work.
But well you could say "absolute==independent of current working dir"
But that's not how std filesystem defines the concept of "absolute path":
Absolute Path A path that unambiguously identifies the location of a file without reference to an additional starting location. The elements of a path that determine if it is absolute are operating system dependent.
So "relative" and "absolute" are implementation-dependent. In Windows, a path is not absolute unless it contains both a root-name and a root-directory. In the Windows filesystem implementation, path("\foo\bar.txt").is_absolute() will be false.
What you're looking for is root_path, see Filesystem TS § 8.4.9, path decomposition:
path root_path() const;
Returns: root_name() / root_directory()
Here's how Microsoft defines it:
Common to both systems is the structure imposed on a pathname once you
get past the root name. For the pathname c:/abc/xyz/def.ext:
The root name is c:.
The root directory is /.
The root path is c:/.
The relative path is abc/xyz/def.ext.
The parent path is c:/abc/xyz.
The filename is def.ext.
The stem is def.
The extension is .ext.
So a truly absolute path would begin with root_name + root_directory, or root_path.
See also system_complete(p) for resolving current directory on other drives:
Effects: Composes an absolute path from p, using the same rules used by the operating system to resolve a path passed as the filename argument to standard library open functions.
[Example: For POSIX based operating systems, system_complete(p) has the same semantics as absolute(p, current_path()).
For Windows based operating systems, system_complete(p) has the same semantics as
absolute(p, current_path()) if p.is_absolute() || !p.has_root_name() or p and
base have the same root_name(). Otherwise it acts like absolute(p, cwd) is the current directory for the p.root_name() drive. This will be the current directory for that drive the last time it was set, and thus may be residue left over from a prior program run by the command processor. Although these semantics are useful, they may be surprising. —end example]
I have a c++ project that I would like to send to someone in executable form. The issue is the program must read from a .txt that I created (specific deliminators). Currently my program reads from a file path that is specific to my computer,
parseFile("/Users/David/Desktop/FinalProject/Store.txt");
How could I package the .txt file and the executable file together, where the exec. reads specifically from the that .txt on anyone's machine?
Note: I am using Xcode
Change your programs to receive 'file path' as a parameter. Write a note(ReadMe) with the program to specify the file format and added a sample data file with the package
tl;dr: if you just put the text file in the same folder with your executable, you can open it with parseFile("Store.txt");
In most runtime implementations, there is a notion of a "working directory." When you open up an executable via the graphical shell (by double clicking it or something to that effect) the working directory is the same as the directory the executable is in.
Now, if you try to open a file in your program via a path that isn't fully qualified, then the path that gets used will be relative to the working directory.
A fully qualified path is a discrete path that points to a single entity in your filesystem. "/Users/David/Desktop/FinalProject/Store.txt" is one such example, as it starts at root (/ on *nix, DriveLetter:\ on Windows) and says exactly which directories you need to traverse to get to your file.
A path that is not fully qualified (which basically means that it doesn't start at the root of your filesystem) can be used to perform relative file addressing. Most runtimes will assume that any path that is not fully qualified is meant to be relative to the working directory, which basically means that the path that actually gets opened is the result of concatenating your provided path to the end of the working directory.
As an example, if you opened your binary, which is stored as /Users/David/Desktop/FinalProject/a.exe, then the working directory would be set to /Users/David/Desktop/FinalProject/. If your program then tried to open "Store.txt", the runtime would see that you're trying to open a path that isn't fully qualified, so it would assume you meant to open a file relative to the working directory, which would then be /Users/David/Desktop/FinalProject/ + Store.txt, which would be /Users/David/Desktop/FinalProject/Store.txt.
The nice thing about this is that if you move your binary, the working directory moves too. if you move a.exe along with Store.txt to /Users/David/Desktop/FinalProject(copy)/, then when you open /Users/David/Desktop/FinalProject(copy)/a.exe, the working directory will be /Users/David/Desktop/FinalProject(copy)/ now, and now when you call parseFile("Store.txt"), it will instead open up /Users/David/Desktop/FinalProject(copy)/Store.txt. This holds true when moving to other computers, too.
It's worth noting that if your binary is run from a command line utility, the working directory will often be the directory the command line shell is in, rather than the executable's directory. It is, however, a part of the C standard that the first command line parameter to main() should be the name of the executable, and most implementations supply you with the fully qualified path. With some minimal parsing, you can use that to determine what path to use as a base for addressing files.
I have a program which is going to take a few different files as input.
All I am going to know is that the files are going to be in the same folder as my program (and I know their names).
Is there a way to write a path to a file knowing only its name and that it will be in the same folder as the main program?
If you are sure the files are in the same folder of your program you could use:
QCoreApplication::applicationFilePath()
You are looking for these from QCoreApplication.
QString QCoreApplication::applicationDirPath() [static]
Returns the directory that contains the application executable.
For example, if you have installed Qt in the C:\Qt directory, and you run the regexp example, this function will return "C:/Qt/examples/tools/regexp".
On Mac OS X this will point to the directory actually containing the executable, which may be inside of an application bundle (if the application is bundled)
Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.
and
QString QCoreApplication::applicationFilePath() [static]
Returns the file path of the application executable.
For example, if you have installed Qt in the /usr/local/qt directory, and you run the regexp example, this function will return "/usr/local/qt/examples/tools/regexp/regexp".
Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.
Depending on your exact use case, you use one of them, probably the former if you wish to get the executable path + your other files appended.
C++ How to get a filename (and path) of the executing .so module in Unix?
Something similar to GetModuleFileName on Windows.
Although it is not a POSIX standard interface, the dladdr() function is available on many systems including Linux, Solaris, Darwin/Mac OS X, FreeBSD, HP-UX, and IRIX. This function takes an address, which could be a pointer to a static function within the module for example (if cast to void *), and fills in a Dl_info structure with information including the path name of the shared object containing that address (in the dli_fname member).
Unfortunately, there is no way to do that using UNIX or POSIX. If you need to use it to look up some sort of data, you should use the $PATH environment variable and search for the data in a path that is relative to each entry in $PATH. For example, it is not uncommon to store binaries in "installdir/bin" for some installation directory "installdir" and to store the associated data in "installdir/share/name_of_program" for some installation directory and some program named "name_of_program". If that is the case, then looking at "../share/name_of_program/name_of_resource_file" relative to each entry in getenv("PATH") is a good way of searching for resources. Another thing you could do is allow the necessary information to be provided on the commandline or in some configuration file, and only perform the search if needed as a fallback option.
Edit
Now that you've stated your rationale for this, I would advise you to simply use the QSettings class from Qt for your configuration information, as it uses the preferred native mechanism for each platform (the registry on Windows, a PLIST file on Mac OS X, the Gnome GConf database on Linux). You may want to take a look at my C++ Project Template as it uses Qt to do just this, and it provides simple commandline options to easily tweak the configuration settings ("--prefset", "--prefget", and "--preflist" manipulate QSettings).
That said, if you absolutely must use an XML configuration file of your own instead of using the preferred native mechanism, I strongly advise you to place the system-wide configuration in "installdir/etc" while placing your library in "installdir/lib" for some installation directory "installdir", as that is the typical place for configuration files on UNIX systems, and "installdir/lib" should ONLY be used for library files, not for configuration files and other errata. I suggest you place a user-specific version of the configuration file in "$XDG_CONFIG_HOME" (if it is defined) or in "$HOME/.config" (where "$HOME" is the user's home folder).
When searching for the system-wide configuration file, I would recommend that you search within $XDG_CONFIG_DIRS if it is defined; if it isn't defined, then falling back to "/etc/xdg" or searching for "../etc/name_of_your_program.conf.xml" relative to "$PATH" and possibly also relative to the "$LD_LIBRARY_PATH", "$DYLD_LIBRARY_PATH", "$DYLD_FALLBACK_LIBRARY_PATH"), the contents of "/etc/ld.so.conf" if it exists, and the contents of "/etc/ld.so.conf.d/*.conf" if those files exist, halting your search as soon as you encounter the first valid such configuration file would be a sensible approach.
Credit goes to Roger for pointing out the XDG Basedir Spec and for his excellent constructive criticisms.
Possible solutions:
You can read the /proc/{PID}/mmap file for the list of shared libraries. Where {PID} is the process pid (you can get it using getpid()).
Call the command line tool ldd for the program binary file (stored in argv[0]).
If you write a solution from scratch take a look of ldd commands source code from uClibc how to get the list of shared libs from an elf binary.
Do any C++ GNU standalone classes exist which handle paths cross platform? My applications build on Windows and LInux. Our configuration files refer to another file in a seperate directory. I'd like to be able to read the path for the other configuration file into a class which would work on both Linux or Windows.
Which class would offer the smallest footprint to translate paths to use on either system? Thanks
Unless you're using absolute paths, there's no need to translate at all - Windows automatically converts forward slashes into backslashes, so if you use relative paths with forward slash path separators, you'll be golden. You should really avoid absolute paths if at all possible.
try boost::filesystem
Filesystem library in boost will probably help you.
There are many ways, IMHO the correct answer is to redesign your program to avoid manipulating paths. I posted an answer here: https://stackoverflow.com/a/40980510/2345997 which is relevant.
ways:
Add a command line option which allows a user to specify the path in question instead of reading it from a config file.
Add a command line option so that the user can specify a base path. Paths in the config file will be interpreted as located under this base path.
Split your config file into three. One file will have cross platform configuration, another file will have windows only configuration and a final file will have Linux only configuration. Then the user can specify the correct path for both Windows and Linux. On windows your program will read the cross-platform config file and the windows only config file. On Linux it will read the cross-platform file and the Linux only config file.
Add preprocessing to your config file parsing. This will allow you to have one config file where the user can make your program ignore some of the lines in the file depending on which OS the program is running on. Therefore, the user will be able to specify the path to the file twice. Once for Linux, and once for Windows.
Change the design so that the files are always located in the same directory as your executable - then the user only specifies file names in the config file rather than paths to files.
Use a simple function that switches "/" to "\". Then document to the user that they must specify paths as Linux paths and this transformation will be applied for windows.
Create your own path mini-language for this and document it to the user. E.g: "/" - specifies a directory separator, {root} - expands to the root of the filesystem, {cwd} - expands to the current directory, {app} - expands to the path to your application etc... Then the user can specify file paths like: {root}/myfiles/bob.txt on both platforms.
Some paths will work on both platforms. E.g: relative paths like ../my files/bill.txt. Restrict your application to only work with these paths. Document this limitation and how your application handles paths to the user.