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.
Related
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.
Many commands access files, and they usually take a path relative to ~/ which I gather is the "home" directory. In my case, C:\Users\Grant\AppData\Roaming\ which is where .emacs.d\ and my init files live.
This is great for Emacs, but not as useful for me. I typically would be over in C:\Users\Grant\Documents\ or my Python script files directory.
Also, I'm using Customize and typing in absolute file names for things like Org capture templates (currently anything I capture goes into files in one particular directory). Not that it's likely that these locations will change, but I was wondering if there are variables I can set for these places, which I can use in Customize or when invoking Dired - maybe some sort of environment variable? And if so, how can I refer to them when typing in a file name?
I have a C Programm which reads from a configuration file during runtime. This file have to be in the same Directory as the executable program. Is there a way to bind or compile the configuration file to to executable that when i copy the executable elsewhere i don't have to copy the configuration file aswell?
Is there a way to bind or compile the configuration file to to executable that when i copy the executable elsewhere i don't have to copy the configuration file aswell?
It is inherent in your configuration file indeed being a separate file from your executable binary that the two can be manipulated independently.
If program configuration is performed only at compile time then yes, you can embed the configuration data into the program. That carries the additional advantage that you then need no file I/O to access the configuration data. That would involve your configuration process generating source code to be compiled into the program.
If yours is a conventional form of configuration file, however, meant to be adjusted some time after compilation, and maybe even by end users, then the configuration data cannot be integrated into the executable binary. In that case, no, what you ask is not possible. You cannot then ensure that the config file is moved or copied whenever the executable is.
Additional thoughts:
Requiring the configuration file to be collocated with the binary is fundamentally problematic on the many systems where the location of the binary on the file system is not directly exposed to the running program.
It is usually better for an executable to rely on a default location for its config file, independent of the location of the binary itself. Such a default location can be system-wide, per-user, or a combination of both.
It is fairly common for programs that rely on config files to have the ability to write a default configuration file, either automatically or in response to a special argument. The automatic alternative is more applicable to programs with per-user configuration than to programs with global configuration, however.
When a program is runtime-configurable via a file, it is usually a good idea to offer the option of specifying the file to use via a command-line argument.
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.
I want to essentially make it so that you never need to unzip/unrar any files. Currently, I have a Dokan filesystem which can do it given a specific zip file but I wanted to know how I can make it apply to all files. Meaning, I want to be able to compile a program that has "fopen("test.zip/1.jpg", "rb");". I think that a Shell Extension would work for dynamically loading the file into the filesystem IF I were browsing in the shell explorer but that doesnt help me with the fopen example. Any ideas?
What you want to do can be used with help of file system filter driver, which would track directory enumeration requests and report directories in place of ZIP files. Then this driver would create virtual files and take the data from ZIP archives. Quite a lot of kernel-mode work, I should say. And file system filter driver is not a file system driver, so dokan won't help you at all.