Home > Software design >  Making a program that lists files in a directory and sorts the output
Making a program that lists files in a directory and sorts the output

Time:10-08

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

CodePudding user response:

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;
            }

CodePudding user response:

    while((rd = readdir(dir)) != NULL){
        list = realloc(list, (count 1)*sizeof(*list));
        list[count] = rd ->d_name;
          count;
        printf("%s\n",rd ->d_name);
    }

Nowhere do you allocate memory to hold the string you're adding to the list. You allocate memory to hold a pointer to it, but that's it.

You need to change list[count] = rd ->d_name; to something like:

    list[count] = malloc(256);
    strcpy(list[count], rd->d_name);

Also, you don't need to allocate new memory for strings when you sort. If you already have memory allocated for every string you need to store (which you must or your list is already broken), why would changing the order require allocating new memory to hold the strings?

  • Related