Search code examples
csortingmallocls

Making a program that lists files in a directory and sorts the output


I use opendir(.) to open a path to the directory I want to read from. I then use readdir with a loop to go through all the files and directories in the current directory. I then have a char** list to store the contents of readdir. I then do a sort on **list to put in lexigraphic order. I keep getting an overflow error when sorting output only when I have a file with a length of over 63 chars. Why is that and how can I fix it?

void ls_short() {
    char **list = NULL;
    int count = 0;
    DIR  *dir;
    struct dirent *rd;
    dir = opendir(".");
    // check to make sure that we can open the directory
    if(dir == NULL){
        perror("Not able to open The current directory.");
        exit(EXIT_FAILURE);
    }
    
    while((rd = readdir(dir)) != NULL){
        list = realloc(list, (count+1)*sizeof(*list));
        list[count] = rd ->d_name;
        ++count;
        printf("%s\n",rd ->d_name);
    }
    printf("here we will print the list\n");
    for (int i = 0; i < count;i++){
        printf("%s\n",list[i]);
    }
    printf("Now we print the list in order and also get rid of . and .. directory\n");
    list = realloc(list, (count+1)*sizeof(*list));
    list[count] = "";
    for (int i = 0; i < count - 1; i++){
        for (int j = 0; j < count - i - 1; j++){
            if (strcasecmp(list[j], list[j + 1]) > 0) {
                    char* temp;
                    temp = (char*)calloc(count, sizeof(char)*256);
                    strcpy(temp, list[j]);
                    strcpy(list[j], list[j + 1]);
                    strcpy(list[j + 1], temp);
                    free(temp);
            }
        }
    }
    for (int i = 2; i < count;i++){
        printf("%s\n",list[i]);
    }
    closedir(dir);
}

This is the error I am getting:

screenshot of error messages

=================================================================
==43335==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges [0x6250000001fd,0x625000000220) and [0x62500000021d, 0x625000000240) overlap
    #0 0x103ef03ef in wrap_strcpy+0xaf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef)
    #1 0x103e9aa5d in ls_short ls.c:61
    #2 0x103e9a5c4 in main ls.c:16
    #3 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

0x6250000001fd is located 253 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
    #0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
    #1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
    #2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
    #3 0x103e9a6ad in ls_short ls.c:42
    #4 0x103e9a5c4 in main ls.c:16
    #5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

0x62500000021d is located 285 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
    #0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
    #1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
    #2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
    #3 0x103e9a6ad in ls_short ls.c:42
    #4 0x103e9a5c4 in main ls.c:16
    #5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

SUMMARY: AddressSanitizer: strcpy-param-overlap (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef) in wrap_strcpy+0xaf
==43335==ABORTING
Abort trap: 6

Solution

  • readdir() has a static buffer for rd->d_name, which it reuses each time you call it, so all your list elements are pointing to the same string.

    You should make a copy of the strings when you assign them to the array.

    list[count] = strdup(rd->d_name);
    

    And when you're sorting, don't copy the names between strings, just swap the pointers.

                if (strcasecmp(list[j], list[j + 1]) > 0) {
                    char* temp;
                    temp = list[j];
                    list[j] = list[j+1];
                    list[j+1] = temp;
                }