How to check if given argument for file reading is valid? - c

I am taking in an argument using fopen. What are some checks I can do to make sure that fopen actually takes in the string to a valid filename?

The number one method is to try opening the file. If fopen() returns NULL, there was an error. Check the errno variable or function to find out the problem.
Trying to preprocess a file specification is an exercise in futility. The operating system will do every relevant check for you, including those which are hard for you to do, like checking file protection ACLs, etc.

The question isn't clear, but if you want to know if the file name you have points to an existing file, you can use access (Linux documentation) (Windows documentation).

Related

fopen() function with a dynamic location in C

I just want to learn that how can I open a file with fopen() function from a dynamic location. I mean, for example it will be a system file and in another computer, this file can be in another location. So if I will set my location in my code not dynamically, my program will not work in another computer. So how Can I set the location dynamically for my program will find this file wherever it is?
You can (and often should) pass program arguments to your main, thru the conventional int argc, char**argv formal arguments of your main. See also this.
(I am focusing on Linux, but you could adapt my answer to other OSes and platforms)
So you would use some convention to pass that file path (not a location, that word usually refers to memory addresses) to your program (often thru the command line starting your program). See also this answer.
You could use (at least on Linux) getopt_long(3) to parse program arguments. But there are other ways, and you can process the arguments of main explicitly.
You could also use some environment variable to pass that information. You'll query it with getenv(3). Read also environ(7).
Many programs have configuration files (whose path is wired into the program but often can be given by program arguments or by environment variables) and are parsing them to find relevant file paths.
And you could even consider some other inter-process communication to pass a file path to your program. After all, a file path is just some string (with restrictions and interpretations explained in path_resolution(7)). There are many ways to pass some data to a program.
Read also about globbing, notably glob(7). On Unix, the shell is expanding the program arguments. You may want to use functions like glob(3) or wordexp(3) on something obtained elsewhere (e.g. in some configuration file) to get similar expansion.
BTW, be sure, when using fopen, to check against its failure. You'll probably use perror like here.
Look also into the source code of several free software projects (perhaps on github) for inspiration.
I would suggest you to use the environment variables, In a PC set your file location as environment variable. then read the environment variable value in your program, then open the file. This idea works both in linux and windows however you have adopt the code based on the OS to read the environment variables.
Besides specifying file location at runtime through command line arguments, environment variables or configuration files, you can implement a PATH-like logic:
Possible locations for your file are set in an environment variable:
export MY_FILE_PATH=/usr/bin:/bin:/opt/bin:$HOME/bin
Your program reads that environment variable, parses its contents and checks existence of file in each specified path, with fopen() return status.

File that hasn't been created

I am doing a c programming assignment where I am working with command-line arguments. One of the notes says that if the file you work with (to my understanding, it will always be "list.csv") is not yet created to create one. Just like vim does when you write "vim new.txt" and new.txt does not exist yet.
I am just wondering if there is a function that tests for the existence of a file? Or do I use some sort of try/catch block?
you can use fopen(). the second parameter says, what to do. Read, create+write, append+create(if not existent)
one way is to use fstat() on the filename.
under UNIX try 'man fstat'
Typically when you want to write to a file the library or operating system API will automatically try to create it for you if it does not already exist. Exactly how you can control this depends on the API that you will be using.

following symbolic links in C

I'm looking to write a C program which, given the name of symbolic link, will print the name of the file or directory the link points to. Any suggestions on how to start?
The readlink() function that has been mentioned is part of the answer. However, you should be aware of its horrid interface (it does not null terminate the response string!).
You might also want to look at the realpath() function, the use of which was discussed in SO 1563186. You could also look at the code for 'linkpath' at the IIUG Software Archive. It analyzes the security of all the directories encountered as a symbolic link is resolved - it uses readlink() and lstat() and stat(); one of the checks when testing the program was to ensure that realpath() resolved the name to the same file.
Make sure that you have an environment which supports POSIX functions, include unistd.h and then use the readlink function.
Depending on the platform, stat() or fstat() are probably the first things to try out. If you're on Linux or cygwin then the stat program will give you a reasonable idea of what to expect from the system API call (it pretty much gives you a text dump of it).
The system call you want is readlink(). Takes a path to the link, returns the string (not always a valid path in the filesystem!) stored in the link. Check the man page ("man 2 readlink") for details.
Note there is some ambiguity to your question. You might be asking for how to tell the "real" path in the filesystem, which is a little more complicated.

MPFR, printf, decimal places, locales, file i/o problem

A user of my program has reported problems reading a settings file written by my program. I looked at the settings file in question and instead of decimal points using the period "." it uses commas ",".
I'm assuming this is to do with locales?
The file i/o is using fprintf and mpfr_out_str for file output and getline combined with atol, atof, mpfr_set_str, etc for file input.
What do I do here? Should I force my program to always use periods even if the machine's locale wants to use commas? If so, where do I start?
Edit: I've just noticed that this problem occurs when specifying the settings file to use on the command line instead of loading it via the GUI - would this indicate a problem on the OP's machine or in my code?
Do you call setlocale at all? If not, I would suggest either embedding the locale used to generate the file in the settings file or force all settings file I/O to use the C locale, via the previous suggestion of setlocale(LC_ALL, "C").
One other option is to use the locale specific formatting functions (suffixed with _l in MSVC) and create the C locale explicitly, via _create_locale(LC_ALL, "C").

Problem replacing Linux system calls using LD_PRELOAD

I am trying to write a program that allows a binary to be run, substituting a certain file when requested with another. It is a library with simple replacements for the system call functions, that is used with LD_PRELOAD. The problem is that it catches opens for reading (the substitute file is read instead), but writes always go back to the actual, specified file. Are there any other "open" system calls I should know about?
Nevermind -- stupid mistake.
Wasn't checking both absolute and relative paths...
I am not sure what the cause of your problem is, but using strace on your program might give some insight. It should be part of any sane Linux distribution.
If it's open for writing, it's most likely going through the creat function (I'm guessing fopen would be redirecting you there). Check your fcntl.h for a complete list.
substituting a certain file when requested with another
Sounds like you check only for the input file (do you check by filename?). You need to check and substitute the output file, too.
If you output goes to one of the standard outputs, then you need to close and reopen them with your output substitute) before you fork into the executable.
To find all system calls that your executable makes you can use strace.
To find all library calls that your executable makes you can use ltrace.

Resources