Thread: What is happening here?

  1. #1
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534

    What is happening here?

    This one has got me stumped. I cannot make heads or tails of it with a debugger, or by looking at it.. I have been looking for a long time..

    The code is altered from the original (first example) found here.

    Here is the changed code that I am playing with:
    Code:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <sys/unistd.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    #include <pwd.h>
    #include <grp.h>
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    
    #define BUFSZ 1024
    
    int main(void)
    {
        DIR *dp;
        struct dirent *dirp;
        struct stat st;
        struct passwd *pw;
        struct group *grp;
        char buf[BUFSZ], *bp, *ftime;
    
        memset(buf, '\0', BUFSZ);
    
        if ((dp = opendir(".")) == NULL) {
            printf("Cannot open this directory\n");
            perror("");
            exit(EXIT_FAILURE);
        }
    
        while ((dirp = readdir(dp)) != NULL) {
            bp = buf;
            do {
                if (dirp->d_reclen != 0) {
                    if (strcmp(dirp->d_name, ".") == 0 ||
                        strcmp(dirp->d_name, "..") == 0) {
                        break;      /* Don't want to list dot and dot-dot */
                    }
                    stat(dirp->d_name, &st);
                    ftime = ctime(&st.st_mtime);
                    ftime[16] = '\0';
                    ftime += 4;
                    pw = getpwuid(st.st_uid);
                    grp = getgrgid(st.st_gid);
                    printf("%3zu %-8s %-7s %9zu %s %s\n",
                           st.st_nlink, pw->pw_name, grp->gr_name,
                           st.st_size, ftime, dirp->d_name);
                }
                bp += dirp->d_reclen;
                dirp = (struct dirent *) (bp);
            } while (dirp->d_ino != 0);
            memset(buf, '\0', BUFSZ);
        }
        closedir(dp);
        return 0;
    }
    The particular bits I don't get are in red. Why make a buffer, set it to zero, make bp point to it, then add the size of d_reclen to it, then turn around cast it as a struct dirent* and assign that to dirp? I am obviously missing something here. I tried doing things like

    Code:
    // bp += dirp->d_reclen;
    // dirp = (struct dirent *) (bp);
    dirp += dirp->d_reclen;
    or

    Code:
    // bp += dirp->d_reclen;
    // dirp = (struct dirent *) (bp);
    dirp += dirp->d_off;
    But they both segfault on me. Why the empty buffer? This thing has got me completely flummoxed.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If you want to move forward by bytes, you have to have a char* -- dirp += dirp->d_reclen moves forward, not eighty bytes, but eighty "struct dirents". I would have expected, not bp = buf, but bp = dirp.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    And what is the point of the
    do ... while (dirp->d_ino != 0);
    loop?

    readdir doesn't return a pointer to a number of directory entries. If you want the next entry, call readdir() again, and just drop the hooky pointer arithmetic assuming there is an array of them.

    Ah, but I see you're using readdir(), where the original example used getdents()
    There's a big difference
    http://linuxreviews.org/man/readdir/
    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.

  4. #4
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    >readdir doesn't return a pointer to a number of directory entries. If you want the next >entry, call readdir() again, and just drop the hooky pointer arithmetic assuming there is an >array of them.

    Best advice I could have gotten I think. I was trying to convert this thing, to make it workable, and I should have scrapped more of the code than I did. I ditched the do..while loop, and the pointer arithemetic, and wonder of wonders, it worked nicely.

    I am having trouble confirming this, but from my reading, it seems that getdents was never truly a Linux system call, but came over from one of the BSDs. Salem, can you tell me if you always had to call it (getdents) with syscall, or did it at one time work under Linux like in the original program that I posted before it was modified? I am just a bit curious about the history of getdents.

    Anyway, thanks for your suggestion. I need to learn that sometimes, just because something 'works,' (or seems to work) it is not necessarily worth learning.
    Last edited by kermit; 02-01-2009 at 11:54 AM.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    I've always used readdir()
    I wasn't aware of anything called getdents until just now, so I can't say where it came from, or anything.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What is happening here PLZ help me
    By jayee_spicyguy in forum C Programming
    Replies: 1
    Last Post: 11-15-2008, 06:47 AM
  2. Explain me what is happening
    By capvirgo in forum C Programming
    Replies: 2
    Last Post: 02-18-2008, 08:26 AM
  3. Weird things happening!!!!!!
    By korbitz in forum Windows Programming
    Replies: 4
    Last Post: 03-22-2004, 06:31 AM
  4. Funny things happening to values outside of function
    By drb2k2 in forum Windows Programming
    Replies: 2
    Last Post: 04-10-2003, 02:39 PM
  5. What happening with my Signiture Text?
    By Davros in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 10-23-2002, 07:33 PM