Reputation: 3
I am trying to 1) Find all files in a directory and display them, 2) Open all found files and read data from them (characters) 3) Output the read data to the screen or a new file.
This is done in C Language and you will see below my current code. The problem that I am running into is that: I can find all the files in my directory and print them to the screen just fine (point 1 above), but when I try to open the found files and read data (characters) from them (point 2 above), I get a segmentation fault.
If I comment out the fscanf(entry_file, "%s", files);
line below, but leave the entry_file = fopen(in_file->d_name, "r");
line, it compiles okay and writes the files to the screen. I also tried indexing the fscanf
line with the int i
(not shown below) and produced the same segmentation fault.
So, how can I read data from these found files? Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL){
printf("Error! Unable to read directory");
exit(1);
}
while( (in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
fscanf(entry_file, "%s", files);
}
closedir(dir);
fclose(entry_file);
return 0;
}
Upvotes: 0
Views: 3876
Reputation: 42129
The two most likely causes of the crash are not checking the return value of fopen
– then either the fscanf
or the fclose
may crash when attempting to use entry_file
when it's NULL
– and the potential overflow of files
.
Another problem which does not cause a crash is that the in_file->d_name
does not contain the full path, but only the name of the file. So if you are testing the code inside /Users/tcn/data
then it will appear to work, but it will fail elsewhere. Either prefix the filename with /Users/tcn/data/
or operate only on the current directory (.
).
Fixes:
if ((entry_file = fopen(in_file->d_name, "r"))) {
(void) printf("%s\n", in_file->d_name);
if (fgets(files, sizeof files, entry_file)) { // or `while`?
// do something with `files`, it will be overwritten for next file
}
(void) fclose(entry_file);
}
And remove the other fclose(entry_file)
from the end of the code.
Also note that if you use this code with an arbitrary directory, it might contain pipes and/or device nodes that will hang forever when you attempt to read them.
Upvotes: 0
Reputation: 34585
You will need a function with a loop using fread()
to replace the fscanf
line, and do a hex dump. For one thing, you don't know if the files are text files or binary files. For another, the segfault could be coming from reading a binary file that contains no newline
into char files[1000];
And even if the files are all text files, you cannot predict that your "generous" 1000 length is enough to hold the first line of text.
Upvotes: 0
Reputation: 9270
Seeing as you are correctly checking for NULL
against dir
and in_file
before using them, the only other thing that could possibly be causing this is entry_file
being null. Check it before using it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL) {
printf("Error! Unable to read directory");
exit(1);
}
while((in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
if (entry_file != NULL) {
fscanf(entry_file, "%s", files);
/* whatever you want to do with files */
fclose(entry_file);
}
}
closedir(dir);
return 0;
}
Note also that, as multiple other users have commented, you should close entry_file
within the loop.
Upvotes: 2