Thread: Sort directory contents on date modified,

  1. #1
    Registered User
    Join Date
    Mar 2012
    Posts
    8

    Sort directory contents on date modified,

    Howdy all,

    I'm a beginner in C trying to build my first application. I need to sort the contents of a directory on date modified. I modified a small struct sorting script. However, somewhere it goes wrong as the output is shuffled but not sorted as intended.

    In addition I get an Segmentation fault: 11 when writing the file name of one particular file to screen (not the other data or filenames). I hope this has something to do with why it doesn't sort as intended.

    Can someone tell me (point me in the right direction) of where it goes wrong?

    Thanks in advance, Maarten

    Original script:
    Sorting Structures : structure sort..«..Structure..«..C Tutorial


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    
      /* A Quicksort for structures of type address. */
    void quick_struct(struct dirent **namelist, int count) {
        qs_struct(namelist,0,count);
    }
    
    int qs_struct(struct dirent **namelist, int left, int right) {
    
        register int i, j;
    
        struct dirent *temp;
        struct stat ibuf;
        struct stat jbuf;
        struct stat xbuf;
                
        i = left; j = right;
    
        stat(namelist[i]->d_name, &ibuf);
        stat(namelist[j]->d_name, &jbuf);  
        stat(namelist[(left+right)/2]->d_name, &xbuf);
    
    
        do {
            while((ibuf.st_mtime < xbuf.st_mtime) && (i < right)) {
                i++;
                stat(namelist[i]->d_name, &ibuf);
            }
            while((jbuf.st_mtime > xbuf.st_mtime) && (j > left))  {
                j--;
                stat(namelist[j]->d_name, &jbuf);
            }
            if(i <= j) {
                temp = namelist[i];
                namelist[i] = namelist[j];
                namelist[j] = temp;
         
                 
                i++; j--;
            }
        
        } while(i <= j);
    
        if(left < j) qs_struct(namelist, left, j);
        if(i < right) qs_struct(namelist, i, right);
    
    
    }
    
    int main(void) {
      
        struct dirent **namelist;
        int n;
        const char *targetdirectory = ".";
        
        n = scandir(targetdirectory, &namelist, 0, alphasort);
        
        struct stat buf;
        
        if (n < 0)
            perror("scandir");
        else {
                quick_struct(namelist, n);
    
            while (n--) {
            
                stat(namelist[n]->d_name, &buf);
                printf("%-23s  %10ld \t %s \n", namelist[n]->d_name, buf.st_mtime, ctime(&buf.st_mtime));
                
                
                free(namelist[n]);
            }
            
            free(namelist);
            
        }
      
      
    
    
    
    }

  2. #2
    Registered User
    Join Date
    Mar 2012
    Posts
    8
    Apparently I forgot to update two structs along the way:

    The segmentation fault remains though, but if I can't figure that one out I'll create a new thread.

    Kind regards, Maarten

    Code:
     
        do {
            while((ibuf.st_mtime < xbuf.st_mtime) && (i < right)) {
                i++;
                stat(namelist[i]->d_name, &ibuf);
            }
            while((jbuf.st_mtime > xbuf.st_mtime) && (j > left))  {
                j--;
                stat(namelist[j]->d_name, &jbuf);
            }
            if(i <= j) {
                temp = namelist[i];
                namelist[i] = namelist[j];
                namelist[j] = temp;
          
                  
                i++; j--;
    
                stat(namelist[i]->d_name, &ibuf);
                 stat(namelist[j]->d_name, &jbuf);  
    
    
            }

  3. #3
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    I haven't looked at your code in any depth but if those lines segfault, you should inspect the values of: i, j, namelist[i], namelist[j], namelist[i]->d_name, namelist[j]->d_name, ibuf and jbuf immediately prior to them.

    I would suggest you do this with a proper debugger, but you can just put each one on a printf on a line of its own before those calls (if you put them all on the same printf, the printf will segfault and it will be hard to tell which part was responsible). My guess is that i and j are out of bounds when you get to that point.

    Oh, and "register" means nothing in any vaguely modern compiler.

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    $ valgrind --db-attach=yes ./a.out 
    ==2092== Memcheck, a memory error detector
    ==2092== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
    ==2092== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
    ==2092== Command: ./a.out
    ==2092== 
    ==2092== Syscall param stat(file_name) contains uninitialised byte(s)
    ==2092==    at 0x4F04DE5: _xstat (xstat.c:38)
    ==2092==    by 0x400794: qs_struct (bar.c:28)
    ==2092==    by 0x400716: quick_struct (bar.c:13)
    ==2092==    by 0x4009C1: main (bar.c:71)
    ...
    (gdb) up
    #1  0x0000000000400795 in qs_struct (namelist=0x51b9330, left=0, right=60) at bar.c:28
    28	    stat(namelist[j]->d_name, &jbuf);
    (gdb) info locals
    i = 0
    j = 60
    temp = 0x4005f0
    ibuf = {st_dev = 21, st_ino = 9046210, st_nlink = 13, st_mode = 16877, st_uid = 1000, st_gid = 1000, __pad0 = 0, st_rdev = 0, st_size = 20480, 
      st_blksize = 4096, st_blocks = 40, st_atim = {tv_sec = 1333383593, tv_nsec = 458878153}, st_mtim = {tv_sec = 1333383588, tv_nsec = 748866984}, st_ctim = {
        tv_sec = 1333383588, tv_nsec = 748866984}, __unused = {0, 0, 0}}
    jbuf = {st_dev = 85694544, st_ino = 85695408, st_nlink = 85692464, st_mode = 85692752, st_uid = 0, st_gid = 85690544, __pad0 = 0, st_rdev = 0, st_size = 4354, 
      st_blksize = 939536896, st_blocks = 80, st_atim = {tv_sec = 0, tv_nsec = 0}, st_mtim = {tv_sec = 60, tv_nsec = 4354}, st_ctim = {tv_sec = 85688496, 
        tv_nsec = 85693232}, __unused = {0, 4354, 939534736}}
    xbuf = {st_dev = 85695120, st_ino = 85695504, st_nlink = 85691824, st_mode = 85689136, st_uid = 0, st_gid = 85691616, __pad0 = 0, st_rdev = 85689856, 
      st_size = 85692656, st_blksize = 85694352, st_blocks = 85691216, st_atim = {tv_sec = 85689344, tv_nsec = 85694032}, st_mtim = {tv_sec = 85694448, 
        tv_nsec = 85692272}, st_ctim = {tv_sec = 85692368, tv_nsec = 85690144}, __unused = {85692560, 85690336, 85689024}}
    (gdb) up
    #2  0x0000000000400717 in quick_struct (namelist=0x51b9330, count=60) at bar.c:13
    13	    qs_struct(namelist,0,count);
    (gdb) up
    #3  0x00000000004009c2 in main () at bar.c:71
    71	            quick_struct(namelist, n);
    (gdb) print n
    $1 = 60
    The first problem is you have j=right, then you try to access namelist[j]
    But this is out of bounds (by 1)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Mar 2012
    Posts
    8
    Muchas gracias all, as noted my loop was going one round too many.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Change file date created or modified (linux/unix/osx)
    By therealmuffin in forum C Programming
    Replies: 1
    Last Post: 03-30-2012, 03:40 AM
  2. Get last modified date and time
    By Babkockdood in forum C Programming
    Replies: 2
    Last Post: 10-22-2011, 06:22 PM
  3. Modified bubble sort
    By jarret_g in forum C++ Programming
    Replies: 4
    Last Post: 01-23-2008, 08:19 AM
  4. Date Last Modified
    By magic.mike in forum Windows Programming
    Replies: 5
    Last Post: 09-23-2005, 05:13 AM
  5. Last modified date?
    By Hoxu in forum C++ Programming
    Replies: 3
    Last Post: 11-15-2001, 12:32 PM