Rami Raghfan
Rami Raghfan

Reputation: 163

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?

Upvotes: 0

Views: 662

Answers (2)

John Bollinger
John Bollinger

Reputation: 181932

You would have a better idea of what is going wrong if you consistently checked the return values of your function calls to recognize when they fail. In this case, you might have been clued in if you had checked the return value of the realpath() calls.

I will suppose that your home directory is /home/ra as your code suggests. Observe that the files you want to open are in /home/ra/Desktop/lab2/folder. You are successfully opening that directory and reading its entries, and those entries give the base names of the files within -- that is, the names without any path components.

Whether you try to resolve those file names by opening the files or by computing their realpath()s, you are doing so relative to the working directory. But the way you are launching the program, its working directory is /home/ra/Desktop/lab2, not /home/ra/Desktop/lab2/folder, so indeed the files the program is asking for don't exist.

Among your options are

  • run the program from the folder containing the files
  • form correct paths to the files with which to open them -- either correct absolute paths or correct paths relative to the actual working directory.

Upvotes: 2

Ken Y-N
Ken Y-N

Reputation: 15018

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");

Upvotes: 1

Related Questions