Opening a file using relative path on Linux in C - c

I'm new to c programming. I have the following directory structure.
Project
|____ dataset
| |_____ data.txt
|
|____ main.c
My code:
FILE *stream = fopen("dataset/data.txt", "r");
or
FILE *stream = fopen("./dataset/data.txt", "r");
returns this error: No such file or directory
But when I use the absolute path it works without any error:
FILE *stream = fopen("/home/<user_name>/C/<project_name>/dataset/data.txt", "r");
What am I doing wrong here?

Read path_resolution(7).
You may want to use chdir(2), since fopen(3) calls open(2) and all of them could fail.
When fopen fails (or some syscalls(2) fails) use errno(3) or perror(3).
Be aware of glob(3), getcwd(2) and fnmatch(3).
See also proc(5).

Related

Why doesn't fopen open existing file? (returns NULL, errno ENOENT)

I have posted this to document my issue, see my self-answer below.
No matter what I try, fopen(...) cannot open the existing file at the path which exists and returns NULL. I am executing the program from a bash script in ~/path. The program file is stored at ~/path/to.
int main(void) {
const char* filename = "my/file"
FILE* fp = NULL;
fp = fopen(filename, "r"); // file is still NULL, segfaults on indirection
if (!fp) exit(1);
fclose(fp);
}
fopen(3) is documented as capable of failing:
Otherwise, NULL is returned and errno is set to indicate the error.
So you should at least code:
FILE* fp = fopen(filename, "r");
if (fp == NULL) { perror(filename); exit(EXIT_FAILURE); };
and fopen won't even try to create a file that you open for reading only.
As a rule of thumb, you always need to check against failure of fopen (a minima like above), and report to your user (with the help of errno(3), perror(3), strerror(3) -used as strerror(errno)- ...) the reason of that failure. An educated user would be able to manage (perhaps with help from his sysadmin).
ENOENT is documented in errno(3) to mean
ENOENT No such file or directory (POSIX.1-2001).
Typically, this error results when a specified path‐
name does not exist, or one of the components in the
directory prefix of a pathname does not exist, or the
specified pathname is a dangling symbolic link.
I find that explanation pretty clear. In your case, you probably don't have any path/ directory in your current working directory, or you do have path/to/my/ directory without any file entry, etc (e.g. path/ exists but without to/ inside it) ....
You could improve your program by showing not only the errno (using strerror(errno) or perror) but also the working directory. See getcwd(3). Or you could leave your user to guess it. Your user could have changed the working directory, e.g. with a cd builtin command of his unix shell.

how to forbid multiple fopen() of same file

I have a C program which opens same file more than one time like this:
FILE *fp1 = fopen("/path/to/file","r");
// Without/beore closing fp1
FILE *fp2 = fopen("/path/to/file","r");
I want to make the second fopen() fail, while I run the program .
Assume I am running my the C programme/executable from GNU Bash shell (/bin/bash), or Bourne shell (/bin/sh).
Is there any setting/configuration I can do in my shell environment such that it will not allow same program to open same file more than one times simultaneously. So that the second fopen() will fail (i.e. will return NULL) ?
You could use open instead of fopen and pass in the O_EXCL flag.

Is it possible to use fopen to read a file with a relative path in C on OS X?

I'm trying to do something like that in my API:
char* fileName = "./path/to/file.bmp";
Texture* tex = (Texture *) malloc(sizeof(Texture));
FILE* file = fopen(fileName, "rb");
But for some reason file is coming up null.
Is there a way to get this file descriptor with a relative path?
I see many questions about that, but nothing that can give me a way to perform this on OS X.
Please check the return value of fopen.
i.e
FILE* file = fopen(fileName, "rb");
if(file==NULL)
{
printf("File can't opened!!");
exit(0)
}
I found a solution. My project folder is something like this:
project
|_ src
|_ examples
|_ example1
|_ main.c
|_ assets
|_ file.bmp
I was trying to get the file descriptor from the main.c. The filePath would be assets/file.bmp, but this isn´t true; I can get the file descriptor with the path from project folder, and the relative file path is examples/example1/assets/file.bmp.
What do you mean by "can't get the file info" ? All your snippet shows is that you've assigned a filename (which happens to be relative to where your process is running), you've assigned a (Texture *) variable, and acquired a file handle by calling fopen().
All fopen() does is open the file for you. If you want get data from the file, you have to fread() or fscanf() it, eg (assuming that the file contents is binary and that we don't care about whether we read the whole file correctly):
(void)fread(tex, sizeof(Texture), 1, file);
Two other things: #1 I'd call my filehandle something different, like fd or inputfd - it helps to reduce the potential for confusion, and #2 use calloc() rather than malloc() - it zeros out the space allocated for you.
What else does your code do?

open file dir problem

I'm running an Linux OS and trying to open file in C compiler like this :
file = fopen ("list.txt", "r");
but the file is not opend!
and when i put the full path like this :
file = fopen ("/home/rami/Desktop/netfilter/list.txt", "r");
it is working!
why the first example is not working?
the list.txt is in the same directory of the c file
thanks.
It's not the directory of the C file that matters, it's your current working directory that does. Try
cd /home/rami/Desktop/netfilter
before running the executable.
Do you know WHY the file didn't open?
Always check the return value of fopen() (and most other functions) and report back a readable error.
file = fopen("file.txt", "r");
if (!file) {
perror("file open");
exit(EXIT_FAILURE);
}
I see you've already found out what your problem is, but the above is a suggestion for the future (and to change your current project)
Is the executable also in the same dir as that of list.txt?
Edit: Actually that doesnt matter. It's the current working dir as per the other answer.

How to open a text file that's not in the same folder?

Since C it's not a language I am used to program with, I don't know how to do this.
I have a project folder where I have all the .c and .h files and a conf folder under which there is a config.txt file to read. How can I open that?
FILE* fp = fopen("/conf/config.txt", "r");
if (fp != NULL)
{
//do stuff
}
else
printf("couldn't open file\n");
I keep getting the error message. Why?
Btw, this only have to work on windows, not linux.
Thanks.
The easy way is to use an absolute path...
my_file = fopen("/path/to/my/file.txt", "r");
Or you can use a relative path. If your executable is in /home/me/bin and your txt file is in /home/me/doc, then your relative path might be something like
my_file = fopen("../doc/my_file.txt", "r");
The important thing to remember in relative paths is that it is relative to the current working directory when the executable is run. So if you used the above relative path, but you were in your /tmp directory and you ran /home/me/bin/myprog, it would try to open /tmp/../doc/my_file.txt (or /doc/my_file.txt) which would probably not exist.
The more robust option would be to take the path to the file as an argument to the program, and pass that as the first argument to fopen. The simplest example would be to just use argv[1] from main's parameters, i.e.
int main(int argc, char **argv)
{
FILE *my_file = fopen(argv[1], "r");
/* ... */
return 0;
}
Of course, you'll want to put in error checking to verify that argc > 2, etc.
You're probably going to want to look into the dirent family of routines for directory traversal.
The location of your .c and .h files is not really the issue; the issue is the current working directory when you run your executable.
Can you not pass in the full path to the fopen() function?

Resources