An absolute path in fopen() - c

I am trying to make my c program more dynamic. It should opens a file with fopen(). Apparently, fopen does not read absolute paths. For example It can't read this path:
fopen("/Documents/projects/cs50_radio/broadcast/source/deadinside.mp3", "r")
returns NULL
;however,
fopen("deadinside.mp3", "r");
returns the expected pointer
I was wondering if there is a possible way to read such a path which might be independent from the current working directory in other cases ?

fopen() can take absolute paths as arguments. Are you working on a unix/linux based OS or on windows? Likely what is happening is you've got the path wrong. If you're on a mac, which it looks like you are, the correct path might be
~/Documents/projects/cs50_radio/broadcast/source/deadinside.mp3
But you can verify by cd'ing into the directory and typing pwd
If you're on windows, your path is definitely wrong, as windows would look more like this:
C:\Documents\projects\cs50_radio\broadcast\source\deadinside.mp3

Related

check if file exists, case sensitive in C

What is a good way to check that a file exists with case sensitivity in C on Windows?
I have got this to work by comparing the filename with the all the file entries in the directory of the filename. Is there a more efficient method in C?
Use this:
WIN32_FIND_DATAA FindFileData;
HANDLE h = FindFirstFile(filenametocheck, &FindFileData);
now FindFileData.cFileName contains the filename as it is stored in NTFS.
All you need to do is compare filenametocheck with FindFileData.cFileName.
Don't forget to close the h handle with FindClose(h) and do error checking.
This works only for checking in the current directory, if filenametocheck contains a path (e.g ..\somefile.txt, or C:\\Somedir\Somefile.txt) you need to do some more work.
For further details read the documentation of FindFirstFile and possibly look into this sample.
Be aware that depending on what exactly you're trying to achieve, this may cause a TOCTOU bug as mentioned in a comment.

C program: determine which directory a file is in

What would be a good method to determine which directory a file is in? I would use realpath(), but that returns the absolute path of the file or directory to which a symlink is pointing.
For instance, if the argument is the basename of a file, and lstat() returns 0, I can confirm that the file exists. But for the purposes of the program I'm working on, I need to determine which directory that file is in.
The project is on GH, so I don't mind posting code here if it helps answer the question. Thanks!
UPDATE: Here are some specifics:
The code is near L64. If the file, dir, or symlink is in .local/share/Trash.test/files/, I need to find the corresponding trashinfo file in .local/share/Trash.test/info/.trashinfo. Normally I truncate the return value realpath() at files/, then append info/, then append the basename and .trashinfo ext. and after that, it does what I need. But when I try to get the realpath of the symlink, the absolute path to it is returned, but it's the path to what the symlink points to (e.g. /home/andy/temp/.local/share/Trash.test/files/dnsmasq -> /usr/share/doc/dnsmasq
No, realpath() does not return the absolute path of the file or directory to which a symlink is pointing. realpath() returns the absolute path of an existing file given a relative path, and as an additional benefit, if a symlink is involved in the relative path, then the symlink will be resolved.
A plain file name in the current directory is also a relative path. So, realpath() is the function you need.
Also: why not try it before posting a question?
there is no unambiguous answer to the question of "which directory hold this file". in unix-like filesystems, there can be any number of file names in any number of directories that all refer to the exact same file (hard links).
even realpath only says that it will give you one fully qualified pathname that refers to the file.
This is how I solved what I was trying to do.
This does some boundary checking. Not relevant to the problem (I see I need to add another check or two though).
buf_check (argv[restore_request], PATH_MAX);
argv[restore_request] is the file to be restored. This can be an absolute or relative path, or it can just be a basename, depending on the current working directory.
strcpy (file.relative_path, argv[restore_request]);
file.base_name = basename (argv[restore_request]);
This places a '\0' in the string: str[strlen(str) - strlen (file.base_name)], in effect, chopping off the basename.
truncate_str (file.relative_path, strlen (file.base_name));
I believe the remaining lines are self-explanatory
strcpy (file.info, file.relative_path);
strcat (file.info, "../info/");
strcat (file.info, file.base_name);
strcat (file.info, DOT_TRASHINFO);
Now the path to the info file can be found, which was the desired result.
I apologize that my question was not clear and didn't provide enough details to properly illustrate my goal. I will make it a point to write better questions in the future. Thanks to all who took the time to give me feedback.

How to read all .txt files in a directory in C

I currently have a short program to read and sort a text tile in C.
If I want to read many files, is there a substitute for:
FILE *f
f = fopen("*.txt", "rw");
Thanks in advance.
f = fopen("*.txt", "rw"); won't work in any case.
The usual way to do this probably depends on your operating system. On Unix-like systems, the simple way is to invoke your program with a command line like "my_pgm *.txt" and let the shell find the matching files. (You'll get multiple arguments, each one being a file name.) I understand that microsoft OSes would require the program to find the files itself.
To do that more or less portably, I'd probably use opendir() and readdir() to examine directory entries and see whether they matched the desired pattern.

Open file in a different directory

I have to do a simple task. I have to open a file which is in a directory. I have the .c file in src, when I compile I move the programs (a.out) in the a bin directory. I want to read a file in the directory asset. All these folders are in a main folder.
If I do this
FILE* fp = fopen("../asset/team_list", "r");
it won't open the file. Why can't I open the file in that directory?
guess you forgot to put the extension of your file
FILE* fp = fopen("../asset/team_list.doc", "r");
Find what error you get using perror/explicit mention of error message and expect a possible reply from stackoverflow.
Make sure you are pointing out to the correct directory where the file is present from the PWD from where your program is being executed.
Relative paths are relative to the current working directory of the process, which might not be the same location as the binary file. So, if you are in /home/user/ and you run ./project/bins/my.exe then your current working directory is /home/user/, relative paths need to be relative to that location.
You can try a few things to help with this issue. First, after the failed open you could examine errno to see why the open failed, is it permissions, invalid path?
Alternatively you might have access to the strace program, this traces system calls, like open from your application, and will allow you to see the failed system call. Try strace ./project/bins/my.exe, you'll see a lot of output, dig through this looking for the failed open call, and try to figure out why this is failing, again the errno will be included in the trace to help understand the failure.
Lastly, you could just add a call to getcwd to your program and print the result (as a debugging aid), this places the current working directory into a buffer, something like this:
char buffer [PATH_MAX + 1];
getcwd (buffer, PATH_MAX + 1);
printf (buffer);

fopen() returning a NULL pointer, but the file definitely exists

The code I have is as follows:
FILE *txt_file = fopen("data.txt", "r");
if (txt_file == NULL) {
perror("Can't open file");
}
The error message returned is:
Can't open file: No such file or directory
The file 'data.txt' definitely exists in the working directory (it exists in the directory that contains my .c and .h files), so why is fopen() is returning a NULL pointer?
Standard problem. Try
FILE *txt_file = fopen("C:\\SomeFolder\\data.txt", "r");
I.e. try opening it with the full absolute path first ; if it works then you just have to figure out what the current directory is with _getcwd() and then fix your relative path.
Is it possible that the filename is not really "data.txt"?
On Unix, filenames are really byte strings not character strings, and it is possible to create files with controls such as backspace in their names. I have seen cases in the past in which copy-pasting into terminals resulted in files with ordinary-looking names, but trying to open the filename that appears in a directory listing results in an error.
One way to tell for sure that the filenames really are what you think they are:
$ python
>>> import os
>>> os.listdir('.')
My problem was that I had a file filename.txt and I didn't realize that in reality it was filename.txt.txt due to windows not showing the extension.
Make sure that your input file is in the same directory as the executable, which may be different than the one where your source files are kept. If you're running the program in an IDE debugger, make sure that your working directory is set to the location of the input file. Also, if you're running in *nix rather than Windows, you may need to prepend a "./" to the input filename.
Invisible SPACE character in file name?
Once a year I have a similar problem:
I try to open a file with the filename in a string, obtained from a sting operation. When I print the name it seems OK, but fopen() returns a null pointer. The only help is printing the name with delimiters showing the exact beginning and end of the filename string. Of course this does not not help with unprintable chars.
I just had a similar issue like this where I knew the path was correct and the file was in the right location. Check the file permissions. It is possible that the program cannot access the file because it is getting permission denied.
I encountered the same errno to fopen on Linux from a script file corrupted by Windows.
ENOENT 2 No such file or directory
Wordpad on Windows (or some other Microsoft culprit) inserted CRLF = (0x0D, 0x0A) into my linux script files in place of newline = LF = 0x0A. When I read the file name into a buffer and called fopen if failed due to the invisible appended CR character.
In the Codelite editor on Linux Mint I was able to show EOL characters (View > Display EOL) and remove them with find and replace, using copy and paste of the CRLF from the corrupted script files and the LF from an uncorrupted file into the text fields.

Resources