1

Final update- Answer is in the comments of the accepted answer.

First of all I realize there are a lot of other answers to this question. I've been through most of them and this code is a combination of going through many other answers. All I want to do is get to the full path to every file in a directory.

#include <limits.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
     DIR *d;
     struct dirent * dir;
     char fullpath[PATH_MAX + 1];
     d = opendir("/home/adirectory");
     if(d != NULL)
     {
          while((dir = readdir(d)) != NULL)
          {
               realpath(dir->d_name, fullpath);
               printf("[%s]\n", fullpath);
               printf("%s\n", dir->d_name);

          }
          // addition of the following line yields
          // Value too large for defined data type
          perror("Something isn't working: ");
          closedir(d);

     }

return 0;
}

Update #3:

The call that fails is dir = readdir(d), which is why I have perror immediately after the while loop.

Update #2:

This works just fine on CentOS, and Ubuntu gcc 4.8.5 +. Does not work on Solaris gcc 4.5.2.

Update: There is an error message:

Value too large for defined data type

...but I'm not sure what could cause this.

This always just prints the current working directory that I'm running the program from. Even so, it doesn't actually list any of the files in that directory besides "." and ".." . What gives? Is there some kind of permission issue? Does this solution not work in 2017?

LBaelish
  • 649
  • 1
  • 8
  • 21
  • 2
    I compiled and ran this as-is and it works fine for me. Do you have read and execute permission on `/home/adirectory`? Try `cd /home/adirectory` and see if you can do `ls` and get results. – lurker Oct 04 '17 at 00:52
  • It works okay for me on Linux. I did change the directory to be my home directory. – wallyk Oct 04 '17 at 00:52
  • Shouldn't I only need read permission? – LBaelish Oct 04 '17 at 00:55
  • @LBaelish to read directory contents you need both read and execution permissions on that directory. – zerkms Oct 04 '17 at 01:14
  • @zerkms I do have read and execution permission on the directory – LBaelish Oct 04 '17 at 01:19
  • 1
    You've not shown any checking of the return value from `realpath()`; it can fail, so you should check what happens. – Jonathan Leffler Oct 04 '17 at 04:17
  • 1
    looks like `realpath` failed, test return value and `errno` against `ENOMEM` or `ENAMETOOLONG`. – Jean-Baptiste Yunès Oct 04 '17 at 05:01
  • The value of `errno`, which is used by `perror()` to determine what error message to emit, is only valid *immediately* after a failed call. Since you're never checking if `realpath()` fails and then you immediately make two `printf()` calls, the error message you see is completely meaningless. – Andrew Henle Oct 04 '17 at 09:36
  • @Jean-BaptisteYunès It's not the call to realpath that fails, it's the call to `dir = readdir(d)` . Also confirmed this by running in gdb – LBaelish Oct 04 '17 at 14:12

1 Answers1

1

the d_name field contains the name of the file in the context of the directory it traverses. So, it does not contain any path, just the name.

So, in order for you to play with its path, you need to append the d_name to the name of the directory, something like the following:

 char *myHomeDir = "/home/adirectory";
 d = opendir(myNomDir);
 . . .
 while((dir = readdir(d)) != NULL) {
    char filepath[PATH_MAX + 1] ;
    strcpy(filepath, myHomeDir);
    strcat(filepath, "/");
    strcat(filepath, dir->d_name);
    realpath(filepath, fullpath);

Of course the stuff above is just a skeleton code for clarity. It could be optimized better and you should use strncpy family of functions.

Serge
  • 11,616
  • 3
  • 18
  • 28
  • So this gets me to the correct path, before it was just printing the path to the current working directory. However I still see the same problem where only . and .. are printed and I get the error message value to large for defined data type. – LBaelish Oct 04 '17 at 02:32
  • Is it compile time or a run-time message? If former, than it should give you a line number, if latter, it sounds like a 32/64 size mix with shared libs. Can you use '-m32' or '-m64' quals for compilation and link? – Serge Oct 04 '17 at 11:44
  • Wow so it looks like `-m64` fixes this issue! Thank you! Although I still don't understand what the problem is exactly if you care to elaborate? – LBaelish Oct 04 '17 at 14:21
  • @LBaelish just looked like you compiled in a 32-bit mode and runtime shared libs were 64-bit. System loader chocked on an attempt to fit some 64-bit data from the lib into a 32 bit variable. – Serge Oct 04 '17 at 15:16
  • This is working for me, so I'm going to accept your answer. Thanks! – LBaelish Oct 04 '17 at 17:31
  • 1
    @LBaelish The default compile mode on 64-bit Linux is 64-bit. The default compile mode on Solaris is always 32-bit and you have to explicitly select 64-bit mode. If one of your files is larger than 2 GB, you can get that error on either OS if you compile 32-bit. On your Solaris system, see [`man lf64`](https://docs.oracle.com/cd/E23823_01/html/816-5175/lf64-5.html) and [`man lfcompile`](https://docs.oracle.com/cd/E23823_01/html/816-5175/lfcompile-5.html#scrolltoc). – Andrew Henle Oct 05 '17 at 09:16