0

I have this function that uses readdir(). I use stat() to get info about the files that are in the directory I give as parameter.

folder_name[] is actually the absolute path for the directory I want to read

The function works fine for names like . or ./lfac but it doesn't work properly for names like ./lfac/comp. I test it and it reads some files from that directory but not all of them. The executable file is placed in the root directory.

I have another function (recursive function) which also uses readdir() and stores a list with the absolute paths of the files that are in the directory (I give as parameter) and its subdirectories. This function has the same problem.

void content(char folder_name[], char *answer)
{                               
    DIR *diropen;
    struct dirent *dirread;

    if ((diropen = opendir(folder_name)) == NULL)
    {
        printf ("Error opening directory %s\n",folder_name);
        exit(EXIT_FAILURE);
    }

    while ((dirread = readdir (diropen)) != NULL)
    {
        struct stat sb;
        memset(&sb, 0, sizeof sb);
        char *temp;
        temp = (char*) malloc (sizeof(char));
        temp[0] = 0;
        sprintf(temp,"%s/%s",folder_name,dirread->d_name);
        if(strcmp(dirread->d_name,".")==0 || strcmp(dirread->d_name,".")==0)
            continue;
        if (stat(temp, &sb) == -1) {
            perror("stat");
            exit(EXIT_FAILURE);
        }

        strcat(answer,"File name:                ");
        strcat(answer,dirread->d_name);
        strcat(answer,"\n");
        strcat(answer,"File type:                ");
        switch (sb.st_mode & S_IFMT) {
        case S_IFBLK:  strcat(answer,"block device\n");            break;
        case S_IFCHR:  strcat(answer,"character device\n");        break;
        case S_IFDIR:  strcat(answer,"directory\n");               break;
        case S_IFIFO:  strcat(answer,"FIFO/pipe\n");               break;
        case S_IFLNK:  strcat(answer,"symlink\n");                 break;
        case S_IFREG:  strcat(answer,"regular file\n");            break;
        case S_IFSOCK: strcat(answer,"socket\n");                  break;
        default:       strcat(answer,"unknown?\n");                break;
        }
        sprintf(temp,"I-node number:            %ld\n", (long) sb.st_ino); strcat(answer,temp);
        .......
    }
}
Jongware
  • 22,200
  • 8
  • 54
  • 100
  • Take a look at this code, and see if it helps you: http://pastebin.com/YEvMnVWB it removes folders recursively – Nelson Teixeira Dec 26 '14 at 13:07
  • 1
    if(strcmp(dirread->d_name,".")==0 || strcmp(dirread->d_name,".")==0) this should check for "." and ".." – lonewasp Dec 26 '14 at 13:14
  • Also on xfs st_mode is not filled in correctly, so you might need to call stat if you need "universal" approach. – lonewasp Dec 26 '14 at 13:16
  • What do you exactly means by "it doesn't work properly for names like ./lfac/comp"? Your code don't recurse into subdirs so it cannot display subdirs contents... – Jean-Baptiste Yunès Dec 26 '14 at 14:21

1 Answers1

0

You are trampling with heavy boots through your computer's memory, so you get Undefined Behavior.

This part

char *temp;
temp = (char*) malloc (sizeof(char));
temp[0] = 0;
sprintf(temp,"%s/%s",folder_name,dirread->d_name);

allocates just 1 byte of memory, per sizeof(char), but the very next thing you do is writing way longer strings into it.

You need to allocate more than that -- at least as much as the length of your folder path, plus the separator, plus the maximally allowed file name length. There are a few constants such as MAX_FILE_PATH you could use, but these are compiler and system dependent; I usually use something "surely large enough, cough cough" such as 1024.

It's not really clear to me why you allocate that memory in the loop, though. (Mainly because you don't free it anywhere, so I don't know the intended scope.) You can do this before your loop, and then you might as well use

char temp[1024];

instead of dynamic allocation.

Jongware
  • 22,200
  • 8
  • 54
  • 100
  • I finally found the problem! The function wasn't the problem. I dynamically allocated the variable answer in a wrong way "(char*) malloc (sizeof(char));" and I allocated more space and now it works for all situations. –  Dec 26 '14 at 14:29