Thread: How to use this part of dirent.h

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

    How to use this part of dirent.h

    I am reading this book, UNIX Filesystems -- Evolution, Design, and Implementation, by Steve D. Pate. I am not convinced it is a great book, as some of his first example code does not even build 'out of the box.' The following is what I am referring to:

    Code:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/dirent.h>
    #include <sys/unistd.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    #include <pwd.h>
    #include <grp.h>
    
    #define BUFSZ 1024
    
    main()
    {
        struct dirent *dir;
        struct stat st;
        struct passwd *pw;
        struct group *grp;
        char buf[BUFSZ], *bp, *ftime;
        int dfd, fd, nread;
    
        dfd = open(".", O_RDONLY);
        bzero(buf, BUFSZ);
        while (nread = getdents(dfd, (struct dirent *) &buf, BUFSZ) != 0) {
            bp = buf;
            dir = (struct dirent *) buf;
            do {
                if (dir->d_reclen != 0) {
                    stat(dir->d_name, &st);
                    ftime = ctime(&st.st_mtime);
                    ftime[16] = '\0';
                    ftime += 4;
                    pw = getpwuid(st.st_uid);
                    grp = getgrgid(st.st_gid);
                    printf("%3d %-8s %-7s %9d %s %s\n",
                           st.st_nlink, pw->pw_name, grp->gr_name,
                           st.st_size, ftime, dir->d_name);
                }
                bp = bp + dir->d_reclen;
                dir = (struct dirent *) (bp);
            } while (dir->d_ino != 0);
            bzero(buf, BUFSZ);
        }
    }
    This is supposed to be a general version of the ls command. Aside from things like missing headers, he makes calls to getdents, which seems to be deprecated (from reading the man page), or perhaps it was never really implemented on Linux to be used by general system programmers in the first place; I don't know, but let's assume that things have changed between now and 2003 when the book was first published -- it does not matter as much to me, as I learn a bit when I am trying to track these problems down.

    Anyway, I started changing the code, to look more like this:
    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 <strings.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;
        //int dfd;
    
        // dfd = open(".", O_RDONLY);
        bzero(buf, BUFSZ);
        if ((dp = opendir(".")) == NULL) {
            printf("Cannot open this directory\n");
            perror("");
            exit(EXIT_FAILURE);
        }
        while ((dirp = readdir(dp)) != NULL) {
            bp = buf;
            dirp = (struct dirent *) buf;
            do {
                if (dirp->d_reclen != 0) {
                    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 = bp + dirp->d_reclen;
                dirp = (struct dirent *) (bp);
            } while (dirp->d_ino != 0);
            bzero(buf, BUFSZ);
        }
        return 0;
    }
    It is not complete, nor correct - I am still working through understanding some of the code. The one part that gets me is this:

    Code:
     if (dirp->d_reclen != 0) {
    The trouble is, when I run the program through the debugger, dirp->d_reclen is always 0. Why?

  2. #2
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    I didn't run your program, but perhaps this line is the issue:
    Code:
    dirp = (struct dirent *) buf;
    Mainframe assembler programmer by trade. C coder when I can.

  3. #3
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Oh man... A case of not being able to see the trees for the forest. Honestly, I was so busy changing stuff just to make it compile, that I *completely* overlooked that. I will have a look and see what I can do...

    Thanks

    edit::

    Yep, that was it. Take that line away and I get much different results. I guess I need to slow down and think more about what I am doing when I am changing a program.
    Last edited by kermit; 01-31-2009 at 10:35 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. segmentation fault... first time with unix...
    By theMethod in forum C Programming
    Replies: 16
    Last Post: 09-30-2008, 02:01 AM
  2. how to get domain part from URL
    By George2 in forum C# Programming
    Replies: 2
    Last Post: 07-23-2008, 12:06 PM
  3. How to get a part of a string from a point onwards
    By pseudonoma in forum C Programming
    Replies: 2
    Last Post: 03-22-2008, 04:09 PM
  4. Replies: 9
    Last Post: 07-11-2006, 04:28 AM
  5. Suspicious Pointer Conversion
    By mr_spanky202 in forum C Programming
    Replies: 35
    Last Post: 04-11-2003, 12:35 PM