Question about file handling - file

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.

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.

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

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.

How to determine if a file is on a FAT system (to see if it really is executable)

I am working at an OS independent file manager, and I divide files in groups, usually based on the extension. On Linux, I check if a file has the executable permissions or not, and if it does, I add it to the executables group.
This works great for Windows or Linux, but if you combine them it doesn't work so well. For example, while using it on Linux and exploring a windows mounted drive, all the files appear to be executable. I am trying to find a way to ignore those files and not add them to the executables group.
My code (on Linux) uses stat:
#ifndef WINDOWS
stat(ep->d_name, &buf);
....
if(!files_list[i].is_dir && buf.st_mode & 0111)
files_list[i].is_exe=1;
#endif
The first part of the answer is to find what filesystem the file is mounted on. To do that you need to find the filesystem using the st_dev field of the stat information for the file. (You can also do this by checking the file path, but you then have to check every path element for symbolic links).
You can then cross-reference the st_dev field with the mount table in /proc/mounts using getmntent_r(). There's an example of that in a previous answer. The mnt_type field will give you the text of the filesystem type, and you'll need to compare the string with a list of Windows filesystems.
Once you've found the filesystem, the only way to identify an executable is by heuristics. As other people have suggested, you can look at the file extension for Windows executables, and look at the initial bytes of the file for Linux executables. Don't forget executable scripts with the #! prefix, and you may need to read into a Jar file to find out if it contains an executable static main() method.
If you are browsing Windows files then you need to apply Windows rules for whether or not a file is executable. If the file extension is .EXE, .COM, .BAT, or .CMD then it is executable. If you want a more complete list then you should check MSDN. Note that it is possible to add registry entries on a machine that makes any extension you want to be considered executable, but it is best to ignore that kind of thing when you are browsing a drive from the network.
The fact is that you are fighting an uphill battle. The reason all the files have executable permissions is that the windows filesystem driver on Linux allows you to specify that as an option. This masks whether or not any files are Linux exceutables, for instance.
However, you could look into the file header for EVERY file and see if it is a Linux ELF executable (just like the Linux file command does).
It might be helpful to start by checking all the information about mounted filesystems so that you know what you are dealing with. For instance, do you have a CIFS filesystem mounted that is actually a Linux filesystem served up by SAMBA? If you enumerate every bit of information available about the mounted filesystem plus the complete set of stat info, you can probably identify combinations that act as fingerprints of the different scenarios.
Another option I could imagine, is to call the file util, and depend on its output (maybe its enough to grep for the words executable / script). This util exist/is compileable for windows (basically it just checks for some magic bytes in the files), too.

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.

Resources