1

I begin in C and i need to use the function realpath but i havn't find many exemple. I helped myself of it : link. My current problem is that my function works for a folder but realpath return null when it's a file.

 while ((dir = readdir(rep)) != NULL)
    {
        if ( !strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..") )
            {
                // do nothing (straight logic)
        } else {
            char buf[_POSIX_PATH_MAX];
            char *path;
            path = realpath(dir->d_name, buf);
            if (!path)
            {
                    perror("realpath");
                    exit(EXIT_FAILURE);
            }
    }

EDIT : The purpose of my function is to have any absolute realpaths for files and folders in the folder dir

Community
  • 1
  • 1
filol
  • 341
  • 2
  • 10
  • You need to check `errno` after calling `realpath` for `EACCES, EINVAL, EIO, ELOOP, ENAMETOOLONG, ENOENT`, or `ENOTDIR` to find out why. I suspect you will find it is `ENOTDIR`. – David C. Rankin Nov 05 '15 at 17:28
  • When i do : `printf("ERROR: %s\n", strerror(errno));` i have : `No such file or directory`. I'm sure of that the file exist. – filol Nov 05 '15 at 17:35
  • What is your working directory? `dir->d_name` is just the base name - the file name *after* the last '/'. – Andrew Henle Nov 05 '15 at 17:47
  • No, the filename is dir->d_name. My working directory is rep or dir after. – filol Nov 05 '15 at 17:58

1 Answers1

1

The problem is you are failing to pass the current directory as part of the name given to realpath. You cannot simply pass dir->d_name (that is just the name of a file or subdirectory below the current directory). You must append dir->d_name (with strcat, etc.) to the directory name you used in your call to opendir. Example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>

#ifndef _POSIX_PATH_MAX
#define _POSIX_PATH_MAX  512
#endif

int main (int argc, char **argv) {

    if (argc < 2) {
        fprintf (stderr, "error: insufficient arguments.  usage: %s dirname\n",
                argv[0]);
        return 1;
    }

    char *p = argv[1];
    size_t len = strlen (p);
    while (*p && p[len-1] == '/')
        p[--len] = 0;

    DIR *rep = opendir (p);
    struct dirent *dir = NULL;

    if (!rep) {
        fprintf (stderr, "error: opendir failed on '%s'\n", p);
        return 0;
    }

    while ((dir = readdir(rep)))
    {
        if ( !strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..") )
        {
            // do nothing (straight logic)
        }
        else {
            char buf[_POSIX_PATH_MAX] = {0};
            char entry[_POSIX_PATH_MAX] = {0};
            char *path = NULL;
            errno = 0;
            strcat (entry, p);
            strcat (entry, "/");
            strcat (entry, dir->d_name);
            printf ("getting realpath for : '%s'\n", entry);
            path = realpath (entry, buf);
            if (!path || errno)
            {
                perror("realpath");
                exit(EXIT_FAILURE);
            }
            else
                printf (" realpath for '%s' : %s\n", entry, buf);
        }
    }

    return 0;
}

Note specifically:

    else {
        char buf[_POSIX_PATH_MAX] = {0};
        char entry[_POSIX_PATH_MAX] = {0};
        char *path = NULL;
        errno = 0;
        strcat (entry, p);
        strcat (entry, "/");
        strcat (entry, dir->d_name);
        printf ("getting realpath for : '%s'\n", entry);
        path = realpath (entry, buf);

Where entry is the string holding the current directory, the separator '/', and finally dir->_dname.

Example/Output

$ ./bin/realpathtst debug
getting realpath for : 'debug/ptrrtn.c'
 realpath for 'debug/ptrrtn.c' : /home/david/dev/src-c/tmp/debug/ptrrtn.c
getting realpath for : 'debug/structinit.c'
 realpath for 'debug/structinit.c' : /home/david/dev/src-c/tmp/debug/structinit.c
getting realpath for : 'debug/leetcode.c'
 realpath for 'debug/leetcode.c' : /home/david/dev/src-c/tmp/debug/leetcode.c
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thx, i work on because for the moment i have core dumped with my code. – filol Nov 06 '15 at 15:08
  • I couldn't figure out how you specified the upper directory of the file you are looking for? Do I need to know where it is, to find exact directory? What If I would like to search for all possible unix terminal commands whose I do not know any upper directory? – Yusuf Kamil AK Dec 02 '17 at 10:58
  • I took the directory to open as the 1st argument given to the program, e.g. `char *p = argv[1];` (I set the pointer `p` to point to the directory given on the command line) Then when I `strcat (entry, p);` I first put the directory in `entry` and then add the separator and filename with `strcat (entry, "/");` and `strcat (entry, dir->d_name);` Let me know if you are still stuck. – David C. Rankin Dec 03 '17 at 06:53