C, Linux, getcwd/chdir(): get binary path - c++

I want to open a number of files (log4cxx configs, other logs etc) relative to binary's location.
Unfortunately, both getwd() and getcwd() are giving me the directory, from which I try to run binary at known path, instead of giving me the path where the binary is located (and where the data is).
How to get the app's path to use it with chdir()? Any methods besides argv[0] and without trying to parse /proc/$PID/ (that's not portable enough)?

Walk the PATH and find an executable of the same name as argv[0]?
However, it would probably be better to provide the user a way to configure where the data is. An env var or config file or CL parameter or something. It's very frustrating dealing with programs that try to be helpful but are actually just stupid.

This is exactly the kind of thing autoconf lives for, and supporting those standard directories is pretty much mandatory if you ever want anyone other than the programmers who wrote your software to use it. Once set up properly, to debug out of your home directory all you have to do is pass a different --prefix= value to configure.

Related

"Embedding" a folder into a C/C++ program

I have a script library stored in .../lib/ that I want to embed into my program. So far, that sounds simple: On Windows, I'd use Windows Resource Files - on MacOS, I'd put them into a Resource folder and use the proper API to access the current bundle and it's resources. On plain Linux, I am not too sure how to do it... But, I want to be cross-platform anyway.
Now, I know that there are tools like IncBin (https://github.com/graphitemaster/incbin) and alike, but they are best used for single files. What I have, however, might even require some kind of file system abstraction.
So here is the few guesses and estimates I did. I'd like to know if there is possibly a better solution - or others, in general.
Create a Zip file and use MiniZ in order to read it's contents off a char array. Basically, running the zip file through IncBin and passing it as a buffer to MiniZ to let me work on that.
Use an abstracted FS layer like PhysicsFS or TTVFS and add the possibility to work off a Zip file or any other kind of archive.
Are there other solutions? Thanks!
I had this same issue, and I solved it by locating the library relative to argv[0]. But that only works if you invoke the program by its absolute path -- i.e., not via $PATH in the shell. So I invoke my program by a one-line script in ~/bin, or any other directory that's in your search path:
exec /wherever/bin/program "$#"
When the program is run, argv[0] is set to "/wherever/bin/program", and it knows to look in "/wherever/lib" for the related scripts.
Of course if you're installing directly into standard locations, you can rely on the standard directory structure, such as /usr/local/bin/program for the executable and /etc/program for related scripts & config files. The technique above is just when you want to be able to install a whole bundle in an arbitrary place.
EDIT: If you don't want the one-line shell script, you can also say:
alias program=/wherever/bin/program

Deploying an executable with a configuration file

I'm new to deploying programs written in C/C++ on Linux and I'm wondering what you'd do in this situation.
I have a binary file (compiled with GNU Make) that needs to read a config file (such as myprogram.conf). But when I write a Makefile to deploy this file to /usr/bin/, where should the config file go? And how does the executable know where it is?
You have endless options, but the best way depends on a couple of things. First, is it a user-specific configuration file, or is it global to all users?
If it's user specific, you could, for example, keep it in ~/.myprogram/config.file and have the program check there. As a service to your users, it's up to you to decide what to do if it's not found -- perhaps copy a default config there from somewhere else, or generate a default, or use hard-coded default options, or display a configuration wizard, or just fail. That's entirely up to you.
If it's global, the traditional place to put it on Linux is in /etc, e.g. /etc/config.file or /etc/myprogram/config.file. See Linux File System Structure. You will generally always have a /etc on Linux. Handling a situation where the file does not exist is the same as above - there's no "right" way to handle that, it's based purely on how convenient you want to make it for a user.
What I usually do for global config files is put them in /etc/wherever on install, have the program default to loading the config file from /etc/wherever, but also give a command line option to override the configuration file (especially useful for testing or other situations).
What I usually do to handle missing config files depends entirely on the application. I'll generally either have hard-coded defaults (if that's appropriate) or simply fail and direct the user to some documentation describing a config file (which I find adequate in situations where my installer installs a config file).
Hope that helps.
It kind of depends on what the configuration parameters are, and whether they are "per system" or "per user" or "per group" or ...
System configurations typically live somewhere in /etc/.... In the same directory that the program lives is a very good place too.
User confgiurations, in the home directory of the user.
Group configurations are the trickiest, as you'll probably need to come up with a scheme where there is a configuration file per "group". /etc/myprog/groups/<groupname>/config or something similar would work.
On Linux, the usual location for configuration files is '/etc', so it is acceptable to deploy a configuration file like /etc/myprog.conf. That requires root privileges however. Other good options include putting a configuration file in the user's home directory, making it something like ~/.myprog.conf or ~/.myprog/.conf to use a folder where you can have several config files, a cache or something else that you want.
As for how the executable knows where the file is, one solution is to look for the file in several common locations. For example, if you decided to place your config in the user's home directory, look for it there first, if not found, look under /etc. And allow a special command line argument that would let a different config file to be loaded. So, say, an invocation of myprog can check for a config file in the home folder, but myprog -c /some/path/config will use /some/path/config as the file. It's also a good idea to have some default settings that you can fall back to if there is no valid config file anywhere.
The config file can go anywhere, but I'd try to put it in the same directory as any other files the program will read or write.
As for how the executable will find it, I'd pass the config file's path to the executable on the command line as an argument, with a default value of "." (which is the current directory, the one you're in when you launch the executable).

How to get the application running path at runtime in c++ [duplicate]

This question already has answers here:
Finding current executable's path without /proc/self/exe
(14 answers)
Closed 7 years ago.
Is there a way in C/C++ to find the location (full path) of the current executed program?
(The problem with argv[0] is that it does not give the full path.)
To summarize:
On Unixes with /proc really straight and realiable way is to:
readlink("/proc/self/exe", buf, bufsize) (Linux)
readlink("/proc/curproc/file", buf, bufsize) (FreeBSD)
readlink("/proc/self/path/a.out", buf, bufsize) (Solaris)
On Unixes without /proc (i.e. if above fails):
If argv[0] starts with "/" (absolute path) this is the path.
Otherwise if argv[0] contains "/" (relative path) append it to cwd
(assuming it hasn't been changed yet).
Otherwise search directories in $PATH for executable argv[0].
Afterwards it may be reasonable to check whether the executable isn't actually a symlink.
If it is resolve it relative to the symlink directory.
This step is not necessary in /proc method (at least for Linux).
There the proc symlink points directly to executable.
Note that it is up to the calling process to set argv[0] correctly.
It is right most of the times however there are occasions when the calling process cannot be trusted (ex. setuid executable).
On Windows: use GetModuleFileName(NULL, buf, bufsize)
Use GetModuleFileName() function if you are using Windows.
Please note that the following comments are unix-only.
The pedantic answer to this question is that there is no general way to answer this question correctly in all cases. As you've discovered, argv[0] can be set to anything at all by the parent process, and so need have no relation whatsoever to the actual name of the program or its location in the file system.
However, the following heuristic often works:
If argv[0] is an absolute path, assume this is the full path to the executable.
If argv[0] is a relative path, ie, it contains a /, determine the current working directory with getcwd() and then append argv[0] to it.
If argv[0] is a plain word, search $PATH looking for argv[0], and append argv[0] to whatever directory you find it in.
Note that all of these can be circumvented by the process which invoked the program in question. Finally, you can use linux-specific techniques, such as mentioned by emg-2. There are probably equivalent techniques on other operating systems.
Even supposing that the steps above give you a valid path name, you still might not have the path name you actually want (since I suspect that what you actually want to do is find a configuration file somewhere). The presence of hard links means that you can have the following situation:
-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo # create a hard link to foo
$ /some/where/else/foo
Now, the approach above (including, I suspect, /proc/$pid/exe) will give /some/where/else/foo as the real path to the program. And, in fact, it is a real path to the program, just not the one you wanted. Note that this problem doesn't occur with symbolic links which are much more common in practice than hard links.
In spite of the fact that this approach is in principle unreliable, it works well enough in practice for most purposes.
Not an answer actually, but just a note to keep in mind.
As we could see, the problem of finding the location of running executable is quite tricky and platform-specific in Linux and Unix. One should think twice before doing that.
If you need your executable location for discovering some configuration or resource files, maybe you should follow the Unix way of placing files in the system: put configs to /etc or /usr/local/etc or in current user home directory, and /usr/share is a good place to put your resource files.
In many POSIX systems you could check a simlink located under /proc/PID/exe. Few examples:
# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond
Remember that on Unix systems the binary may have been removed since it was started. It's perfectly legal and safe on Unix. Last I checked Windows will not allow you to remove a running binary.
/proc/self/exe will still be readable, but it will not be a working symlink really. It will be... odd.
On Mac OS X, use _NSGetExecutablePath.
See man 3 dyld and this answer to a similar question.
For Linux you can find the /proc/self/exe way of doing things bundled up in a nice library called binreloc, you can find the library at:
http://autopackage.org/docs/binreloc/
I would
1) Use the basename() function: http://linux.die.net/man/3/basename
2) chdir() to that directory
3) Use getpwd() to get the current directory
That way you'll get the directory in a neat, full form, instead of ./ or ../bin/.
Maybe you'll want to save and restore the current directory, if that is important for your program.

File I/O from current Windows position C++

I have not yet found a definitive answer about this. I am trying to have access to files in subfolders from my .EXE. When I have asked before, people tell me to use the absolute location i.e. "c:/game/info/" if I wanted to access something in /info/
But it is completely unreasonable for me or anyone to assume that someone is going to use their program from the same directory. What if the user only has a D drive? That sort of thing.
So my question is: how can I access a file in a subdirectory from my executable without relying on the entire path?
Your title says "Windows", so I'll give a WinAPI-specific answer.
On Windows, you can find your application directory with GetModuleFileName(NULL, ...), and PathRemoveFileSpec. Then PathAppend will make the full path to your data files.
Or you can store the data inside you .exe file as Win32 resources, so they never get separated.
Please note that this approach generally works only for read-only access to data files. If you try to write files in your application directory, you might be blocked by ACLs (depending on install location and local security settings of the computer).
Use GetModuleFileName (Retrieves the fully-qualified path for the file that contains the specified module. The module must have been loaded by the current process.)
char strExePath [MAX_PATH];
GetModuleFileName (NULL, strExePath, MAX_PATH);
You'll then need to extract the folder path (someone has already posted how to do that), and combine your path.
Make or use an installer that asks the user where to install the executable and writes that path to the registry in a well-known location for later reference.
if you use:
#include <fstream>
ifstream stream("file");
it will be working. "file" is file in directory with your exe. Of course if you want go up or down in folders hierarchy use "..\file" or "folder\file"

C++ How to get a filename (and path) of the executing .so module in Unix

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.