Guillermo Gruschka
Guillermo Gruschka

Reputation: 167

Reading directories using readdir_r

I've been checking and fighting with this procedure without success for quite a while, hope you can help me out.

The idea is to read the directory stored in c_Localpath and copy the read dirs into c_namesLocal to return them.

Am I doing something wrong in my implementation? The program breaks on the strcpy, and I have no clue why.

DIR* ptr_dir = opendir(c_Localpath);

char** c_namesLocal = calloc(1, 256);

    size_t numElements = 0;
    int returnCode =0;
    struct dirent ptr_PrevDirEntry;
    struct dirent* ptr_DirEntry = NULL;
    returnCode = readdir_r(ptr_dir, &ptr_PrevDirEntry,
            &ptr_DirEntry);

    while ((returnCode ==0) && (ptr_DirEntry != NULL)) {
        char* name = c_namesLocal[numElements];
        strcpy(name, ptr_DirEntry->d_name);
        ptr_PrevDirEntry = *ptr_DirEntry;
        returnCode = readdir_r(ptr_dir, &ptr_PrevDirEntry,
                &ptr_DirEntry);
        numElements++;
        c_namesLocal = realloc(c_namesLocal, 256 * numElements);
    }

Upvotes: 3

Views: 10682

Answers (3)

Rohit
Rohit

Reputation: 624

Sorry for replying after 2 years. But I wanted to help others who would like to know the answer. I have worked on the implementation of readdir_r and thus I have modified your code to make it work. I cannot say the codes as a whole would work but, it is definite that you could get the next file entry in the indicated directory you mentioned. And thus you could save those entries into other var and could do whatever you would like to.

Please see below.

DIR* ptr_dir = opendir(c_Localpath);
size_t numElements = 0;
int returnCode =0;
struct dirent *ptr_PrevDirEntry = NULL;
struct dirent *ptr_DirEntry = NULL;
int len_entry;
char *c_namesLocal = NULL;

len_entry = offsetof(struct dirent, d_name) + fpathconf(dirfd(ptr_dir), _PC_NAME_MAX) + 1;
ptr_PrevDirEntry = malloc(len_entry);

if(!ptr_PrevDirEntry)
        exit(0);

for(;;){
        readdir_r(ptr_dir, ptr_PrevDirEntry, &ptr_DirEntry);
        if(!ptr_DirEntry)
            break;
        else
        {
                 if((strcmp(ptr_DirEntry->d_name, ".") != 0) && (strcmp(ptr_DirEntry->d_name, "..") != 0)) // skip "." and ".." file listings
                 {
                    //Perform copying or do whatever you want with the file entry read from the dir "c_Localpath"
                    //Increase numElements to 1 and keep on increasing by 1 on every iteration
                    numElements++;
                    //realloc everytime you find next entry
                    c_namesLocal = realloc(c_namesLocal, 256 * numElements);
                    //copy the next file name in the c_namesLocal[0], c_namesLocal[1] and so on.
                    strcpy(c_namesLocal[numElements - 1], ptr_DirEntry->d_name);
                 }
        }
 }

 //free "ptr_PrevDirEntry" before returning and take care of "c_namesLocal" as well.

The codes above are self-explanatory. I hope it helps you. Cheers :)

Upvotes: 6

LSerni
LSerni

Reputation: 57378

In this code:

char* name = c_namesLocal[numElements];
strcpy(name, ptr_DirEntry->d_name);

name starts as NULL. You initialized a vector of pointers, but the single pointers themselves still point to NULL. You ought to allocate memory for the d_name:

// You no longer need '*name'
c_namesLocal[numElements] = strdup(ptr_DirEntry->d_name);

Then it would be prudent to add a check:

if (NULL == (c_namesLocal[numElements] = strdup(ptr_DirEntry->d_name)))
{
    // signal out of memory and return
}

And the same check when you realloc the vector of pointers.

Upvotes: 0

Musa
Musa

Reputation: 97672

This is a null pointer exception, c_namesLocal actually points to a sequence of 256/sizeof(char*) char * pointers all set to null by calloc, so c_namesLocal[numElements] == 0. You have to allocate memory for each entry.

Upvotes: 0

Related Questions