Search code examples
clinuxdirectoryfile-handling

How to properly use realpath() for reading multiple files within a directory?


This is supposed to be a program that reads multiple files within a directory and gets the frequency of a given word across those files, I know that part is incomplete for now.

fopen() is returning null to files that exist and have permission 777.

here is permissions from the terminal:

ra@ra-VirtualBox:~/Desktop/lab2/folder$ ls -l
total 12
-rwxrwxrwx 1 ra ra 21 mar 14 23:20 file1.txt
-rwxrwxrwx 1 ra ra 21 mar 14 23:20 file2.txt
-rwxrwxrwx 1 ra ra 21 mar 14 23:20 file3.txt

and here is the output obtained after using errno as suggested by this answer

with buf printed

READING FILE: /home/ra/Desktop/lab2/file3.txt

fopen: No such file or directory
READING FILE: /home/ra/Desktop/lab2/file1.txt

fopen: No such file or directory
READING FILE: /home/ra/Desktop/lab2/file2.txt

fopen: No such file or directory

Edit: from output I noticed that realpath() somehow erased an entire subdirectory before going to the file. /folder/ is not there and /home/ra/Desktop/lab2/file*.txt does not exist!

And the code as follows:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <dirent.h>

#include <unistd.h>

#include <pthread.h>

#include <limits.h>       //For PATH_MAX

typedef struct {
  FILE * fptr;
  char * word;

}
inputFile;

void * readFrequenciesFromFile(void * path) {

  static int count = 0;

}

int main(int argc, char * argv) {

  int i;

  char buf[PATH_MAX + 1];
  char * wordToSearch = "test";

  DIR * dir;
  FILE * entry_file;
  struct dirent * in_file;

  // notice that the full directory is used here
  // but buf somehow does magic and tells me the files
  // are in /lab2/ directory
  dir = opendir("/home/ra/Desktop/lab2/folder");

  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;

    realpath(in_file -> d_name, buf);
    entry_file = fopen(buf, "r");
    // printf("READING FILE: %s\n", buf);
    if (!entry_file) perror("fopen");
    if (entry_file != NULL) {
      pthread_t tid;
      inputFile * args = malloc(sizeof * args);
      args -> fptr = malloc(sizeof entry_file);
      args -> word = wordToSearch;

      if (pthread_create( & tid, NULL, readFrequenciesFromFile, args) == 0) {
        printf("Creating thread for file [%s] with ID %ld\n", in_file -> d_name, tid);
      } else {
        free(args);
      }

      fclose(entry_file);
    }
  }

  closedir(dir);
  return 0;
}

I will mention that I'm using Ubuntu 18.04 on VirtualBox Version 6.1.10 r138449 (Qt5.6.2)

Where do I begin to solve this problem? Is this even plausible or have I missed something?


Solution

  • I see ra@ra-VirtualBox:~/Desktop/lab2/folder$ has folder but READING FILE: /home/ra/Desktop/lab2/file3.txt does not. The problem is that the default directory is ~/Desktop/lab2/, and that is what realpath() uses; perhaps adding chdir() will help:

    chdir("/home/ra/Desktop/lab2/folder");
    dir = opendir("/home/ra/Desktop/lab2/folder");