Is the Windows directory a place for temporary files - GetTempPath function - c

I am creating a small library in C, for Windows only, to help me when I want to create an application.
I came across the topic of creating temp files.
I looked at the GetTempPath function documentation and I saw that it uses the first existing environment variable in this order:
The path specified by the TMP environment variable.
The path specified by the TEMP environment variable.
The path specified by the USERPROFILE environment variable.
The Windows directory.
The question is: if for some reason the first three variables don't exist and the function returns the Windows directory C:\Windows\, is this directory a place to put temporary files?
If it is not then why does the function return it?
EDIT: then where should I put the temporary files?
I don't want throw Access Denied Error or Temp Path Not Found Error

C:\Windows\, is this directory a place to put temporary files?
Definitly it is not. (This assumes C:\Windows\ is the Windows Directory as returned by GetWindowsDirectory ()).
Also on any recent Windows installation normal users won't even be able to write anything to the Windows Directory (e.g. C:\Windows\).
If none of the above three env/ var/s is set let your application create its own directory for temporary files, that is typically located somewhere in the user's home directory.
If your application investigates on this during installation it might consider setting TMP or TEMP to a reasonable directory and create the latter.

This post may not answer the question, but it can explain what is going on and how to fix potential problems:
The MSDN documentation says that GetTempPath evaluates a number of environment variables.
However, the Cygwin documentation says that the environment is stripped away from the process. A Cygwin process will therefore not have the necessary environment variables in its context. Conclusively, GetTempPath cannot catch them and defaults to the Windows directory.
Solution: There is a function which syncronizes the environment of your process with the surrounding Windows environment:
#include <sys/cygwin.h>
...
cygwin_internal (CW_SYNC_WINENV);
See the Cygwin documentation.

Related

Do you need to be specific about a file location when using os or do you still ned to write (folder/file)?

Let's say I have a file called hello.txt in the folder called coding, and I want to open that in python. I know that if I don't use os, I would have to write open("coding/hello.txt") but if I would write os.open would I still have to specify the folder like ("coding/hello.txt") or can I just write os.open("hello.txt") because I am using os?
"File" and "operating system" can mean a lot of different things, but typically operating systems have the concept of a "current" or "working" directory. Each process has its own current directory, and if you don't specify a directory for a file it uses the current directory.
Do not rely on this. Too many things can change the current directory unexpectedly, and your program will suddenly start using a different file.
Instead always specify the full file path like open("/usr/tmp/coding/hello.txt") or whatever is appropriate for your operating system; it will probably provide environment variables or something for the user's home or temporary directories.
Note that your examples "coding/hello.txt" and "hello.txt" both use the current directory, and are different files.

Finding file locations in offline softwares in C

At some point in my C program I have to deal with something like this.
FILE * fptr = fopen("/Parent/child/.../file.dat");
Which means in order to access any file I need to know it's location. That's all understandable.
But, how can I make this generic? In my computer "/Parent/child/.../file.dat" will work because that's where the file is stored, but I'm making a software to distribute to other users so the path obviously differs. My question is, how can I install a specific file into the user's computer such that I can know and get the location of that file. I a but confused about this concept so any resources that could help me understand it better would be greatly appreciated.
In Linux the default path to application files should be hardcoded. There is a standard which applications should follow. For example, architecture-independent files should go to /usr/share/ and then either your application name or, if you expect the data to be shared between applications, a generic category such as images. User-specific configuration files should go $HOME/.config/<app-name>. Older applications place their default configuration in $HOME/.<app-name> instead.
You should also provide an ability to override the default path to the data with a command line switch and/or an environment variable and/or a user configuration file (the location of the latter should also be overridable with a command line switch and/or an environment variable).
Some applications search for their data directory relatively to the executable position. An executable can know its own absolute path by reading /proc/self/exe symbolic link. For example, if an executable finds itself in /usr/local/bin/somename, it can look for /usr/local/share/<app-name> (two levels up from the executable name and down to share/<app-name>.).
Finally, if you distribute source code for the users to build, the file locations should be configuration parameters.

GetPrivateProfileString and AppData VirtualStore directory

I have a program which reads GetPrivateProfileString from a file ".\abcd.ini" - i.e. it will look for the ini file in the current directory.
If it does not find the ini file, it has a default value set in the 3rd parameter to GetPrivateProfileString.
I have an installer which installs the program to c:\program files (x86)\abcd\client directory.
Initially, the installer also installed an abcd.ini file in the same directory with a particular profile string key/value pair. Post that, I changed the installer to not install any ini file.
However, the program continued taking the value from the old ini file which I had shipped even if it didn't exist in that directory.
After doing a system wide search I found a copy of abcd.ini in c:\Users\myusername\AppData\Local\VirtualStore\Program Files (x86)\abcd\Client
Once I deleted this, the program worked correctly (as if there is no ini file).
Googling it seems that the virtualstore is used because myuser does not have full permissions for c:\program files (x86). However, the program itself doesn't write to the ini file, it only reads from it.
Is this actually how it's supposed to be? Why is the ini file copied to AppData & why does the program read from there if there is no local copy?
I am on Windows 10 64 bit.
The diagnostic is that the EXE program does not contain a manifest that declares itself compatible with UAC. Not unusual for the kind of app that still uses GetPrivateProfileString().
Is this actually how it's supposed to be?
Yes, this the way modern versions of Windows (major version >= 6, Vista and up) deal with legacy programs that assume the user always has admin privileges. Redirecting the file access to the VirtualStore directory ensures that the missing access rights to Program Files directory does not cause trouble.
it only reads from it
The OS does not have a time machine to guess whether you might write to the file and did so in a previous session. So it has to check the VirtualStore directory first. To find that .ini file.
It is also important to not assume that it was your program that got the .ini file in that directory. It could have been done by another ancient program, like a text editor. Or a previous version of your program. Or the installer you use.
Yes, because the program would crash, so Windows redirects the program to the VirtualStore directory.

Rely on PATH or provide an explicit path when using system()

I'm writing a 'C' program that makes several calls to system() to execute other programs. When constructing the command string is it better to explicitly give the full path to the program being called, or should I just give the executable name and let the shell resolve its location using the PATH environment variable?
The programs I'm calling are all part of a single package and I have the path to the installation directory from a preprocessor definition. Giving the explicit path would seem to avoid errors that might occur if multiple installed programs share the same name. However it makes building the command strings a little more complicated, and everything will break if the user moves the programs around after installation.
Is there a widely accepted best practice covering this?
[Clarification]
I'm using autoconf/automake to generate the distribuion. The preprocessor definition providing the installation directory is created by the makefile. It reflects the user's choice of the installation directory as specified either on the configure comamnd line or the make command line. I do take the point about using environment variables to specify the location for the binaries though. It seems like an unneeded pain in the butt to make users rebuild just to change the location of the binaries.
Best practice is never to assume that you know your install directory at build time. Let your users decide where to install and work anyway.
This means that you will need to find out where your programs are located using some other mechanism. Consider using environment variables or command line parameters to allow the user to specify the actual path, if your platform does not provide you with the means to find out where the executables are located. You can use your knowledge of where you are normally installed as a fallback option.
For your actual question, in case you can build the absolute path to your program (using another mechanism than preprocessor directives) - use that. Otherwise, fall back to having the system find out for you.
The best practice is to not presume anything about the system you're installing onto. You can have the best of both worlds if you just let the user choose. Make the command you call an application preference or require paths to be defined in the environment:
PATH_TO_TOOL1=foo
PATH_TO_TOOL2=/usr/bin/bar
You can, of course, just fall back to a default of some kind if the variables aren't defined or the preference isn't set. Writing your application to be more flexible is always the best choice!
You should definitely let the user specify the path with an environment variable to the installed binaries. Not all systems are the same and many people will want to put their execs in different places.
the best example I can think of is people doing a local install vs system install. If your program is installed in a home directory that user will have to set and env variable to say where the binaries are copied to.
If you're absolutely sure of the path names, and if they are not "well-known" commands (for example, POSIX shell utilities on Unix are "well-known"), you should specify the pathname, otherwise don't specify the full path, or let the user control it by using an environment variable.
In fact, you may be able to write something like a function such as int my_system(const char *);, which does the prefixing of the path for you. If later you determine that it was a bad idea, it's just a matter of making my_system() identical to system().
I'm not sure if it's a best practice, but what I do in these cases is I write my C code to extend the PATH environment variable to include the installation directory at the end. Then I just use the PATH. That way, if the user's PATH wants to override where I believe the stuff was installed, it can—but if the software was installed in an out-of-the-way place, I can call it without forcing my users to put the directory on $PATH themselves.
Please note that the extended PATH lasts only as long as the C program runs; I'm not proposing changing the persistent PATH.

Question about file handling

Hey, I wanted to know if anyone can tell me what the difference between "file.file" and "./file.file" is. It seems to make quite a significant difference in my programs to call
OpenFile("./file.file");
EDIT: My mistake, I thought my question was a generic one. This is in C++ using standard library functions.
In general, "./File" will be relative to the directory that your program's context is currently executing in.
Just "File" will be relative to the directory that the program executable resides in.
This is pretty dependent on what tool or language you're using, however.
If you're referring to the WinAPI function, see the remarks section on this MSDN page:
Remarks
If the lpFileName parameter specifies
a file name and extension only, this
function searches for a matching file
in the following directories and the
order shown:
The directory where an application is loaded.
The current directory.
The Windows system directory.
The 16-bit Windows system directory.
The Windows directory.
The directories that are listed in the PATH environment variable.
The ./file.ext means that it must be in the current directory, whereas not specifying a directory means it can be in any of the places normally checked.

Resources