Search code examples
clinked-listmemsetrealpath

Confustion with realpath() buffer


Here's my function, which is looking for regular files in given directory, and then storing full path to them in a list.

static my_func(const char *path, Files **list) //list - storage for file names
{
    DIR *d;
    struct dirent *dir;
    char buf[PATH_MAX + 1];

    d = opendir(path);
    if (d) {
        while ((dir = readdir(d)) != NULL) {
            if ((DT_REG == dir->d_type)) {

                realpath(dir->d_name, buf);
                List_push(list, buf);
                printf("%s\n", dir->d_name);
                // memset(buf, 0, PATH_MAX + 1);
            }
        }
    }
    closedir(d);
    return 0;
}
...
...

int main()
{
    // list creation
    // my_func call
    ...
    List_print(...)
}

Expected output:

FILE_1.txt
FILE_2.txt
FILE_3.txt
FILE_4.txt
FILE_5.txt
/home/user/c/FILE_1.txt
/home/user/c/FILE_2.txt
/home/user/c/FILE_3.txt
/home/user/c/FILE_4.txt
/home/user/c/FILE_5.txt

The current output:

FILE_1.txt
FILE_2.txt
FILE_3.txt
FILE_4.txt
FILE_5.txt
/home/user/c/FILE_1.txt
/home/user/c/FILE_1.txt
/home/user/c/FILE_1.txt
/home/user/c/FILE_1.txt
/home/user/c/FILE_1.txt

Can it be related with my linked list implementation? It works fine, because I tested it with:

List_push(list, dir->d_name)

and got expected results. This is implementation of List_push (Files is just simply struct with char * and pointer to the next element):

void List_push(Files **head, char *x)
{
    Files *new;

    new   = malloc(sizeof(Files));

    if (NULL != new) {
        new->next = *head;
        new->text = x;
        *head = new;
    } else {
        printf("malloc error");
    }

}

Also, as you can see, I was trying to clear buf with memset, but without success - the output is:

FILE_1.txt
FILE_2.txt
FILE_3.txt
FILE_4.txt
FILE_5.txt






[console]$

Yes, blank space seems to be filed with something (or these are just '\n' symbols from List_print), so list is not empty.

What is wrong here?


Solution

  • In List_push(list, buf); you store a pointer to buf in the list. You do this for each file, so you end up with several pointers to the same buf in the list. When printing the list items it then will show the (current) contents of buf.

    To avoid this you need to create a copy of buf and store that, so that the stored data won't be overwritten when you reuse buf for the next file.