Thread: version of ls -l bug, only takes cwd :(

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    3

    version of ls -l bug, only takes cwd :(

    Hi everyone,

    I am brand new to this board and I hope that I do not violate any rules too bad here, although they seem pretty easy to follow.

    I am writing a version of "ls -l" on a UNIX platform and although I am not yet finished adding the details of the system call stat(), I do not want to proceed adding file information until I can figure out why I am having the following problem for a reason I have spent hours and hours trying to figure out:

    * if my argv[1] is passed nothing, my program assumes we want the "ls -l" of the current working directory. So, no problems there. But, since I added the stat() system call to convert my program from strictly an "ls" program to a "ls -l" program, I can no longer pass a directory name from the command line (i.e. a.out pathname) and read out all of the files in a directory that is not the cwd.

    This is the code, which is my first try at ever implementing this, so if it isn't pretty or kosher, my sincere apologies, and i will improve in the future making things neat. (I am pretty new to C) :


    Code:
      
    
    #include <stdio.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/errno.h>
    #include <unistd.h>
    
    
    
    
    
    
    
    int main(int argc, char* argv[])
    {
       
      DIR *dstream = NULL;
    
      struct dirent *listing;
      struct stat fileinfo;
    
      
      /* Open chosen directory stream */
      
      if(argc == 1){                       /*no argument supplied so assume cwd.*/
        dstream = opendir(".");
        if(dstream == NULL){
           printf("Error: Unable to open current directory.\n");
           exit(-1);
          }
        else
          {
            printf("Current working directory stream opened.\n\n\n");
          }
       }
    
      else{                                        /*Argument for dir. supplied.*/
            dstream = opendir(argv[1]);
            if(dstream == NULL){
              printf("Error: Unable to open specified directory.\n");
              exit(-1);
            }
          else
            {
              printf("%-6s directory stream opened.\n\n\n", argv[1]);
            }
       }
    
    
      /*Processing the directory stream. */
    
    
      while((listing = readdir(dstream)) != NULL)
        {
          if(stat(listing->d_name, &fileinfo) == 0)
               {
                 printf("%2d\t%-10.10s\n", fileinfo.st_nlink,listing->d_name);
               }
    
             else
               {
                 printf("Error: Directory stream unable to be processed.\n");
                 perror("readdir");
                 exit(-1);
               }
          }
    
     /*Closing the directory stream. */
    
      if((closedir(dstream)) == -1) /* closedir() returns -1 on fail. */
    
       {  printf("Error: Directory stream not closed.\n");
          exit(-1);
       }
    
      return 0;                     /*otherwise, closedir() succeeded, return.*/
    
    }

    I hope I tagged that correctly. So the problem lies, I think anyway, in the stat() system call in the processing section of the program. I attempted to somewhat neatly organize the program into three logical sections, opening the directory, processing the directory, and then closing the directory.

    Note: when I pass a subdirectory as the argument into argv[1], I do get the "." and ".." for the present and parent directories, and their number of hard links, which are the two attributes I added to this program before I discovered this bug. After these two are read-out though, I get the errno = 2 error, which is "No such file or directory". Why is the subdirectory after these two iterations no longer readable to readdir()? I used perror() to discover this as the cause, which I'm sure is obvious to everyone else here who certainly knows more than I do.

    Can anyone tell me where I went wrong and made a rookie mistake? How do I need to rework the while loop and the stat() call so that I can pass in any subdirectory from the command line without getting an error?

    I would be eternally grateful, emphasize, eternally!

    Thanks so much in advance to anyone who takes the time to read my code,

    CHL

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > listing->d_name
    This is relative to the directory it is in, not the full path you specified.

    Try printing this out before doing stat() on it, you'll see what I mean.

    The easiest thing to do is do a chdir(argv[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.

  3. #3
    Registered User
    Join Date
    Jun 2007
    Posts
    3

    Thank you!

    Thank you so much.


    What is equally ironic (and somewhat depressing for me haha) is that I actually did try using chdir(argv[1]) after many hours of looking up a function to change a directory....i placed it after you suggested it at the beginning of the while loop before the stat() and now it works perfectly...when I tried it, it was after the stat() but this produced the error for which i originally posted.

    I am too much of a novice to UNIX systems programming to really full understand why chdir(argv[1]) wouldn't work if it was after the stat() call but apparently, that made all the difference. I am considering aspiring to be a UNIX System Admin. and this program has been as in depth with UNIX as I've ever been, but I've learned a ton. However, I do hope that either I will figure it out eventually why this happened (after I better understand the nature of stat()) or someone is so kind as to explain why putting the chdir(argv[1]) after the stat() call produced the bug.

    P.S. I wasted a good 7 hours trying OTHER things to solve the bug before just trying to place chdir(argv[1]) in a different place in the while loop.


    Had it not been for your help, I'd have probably never went back to it and really been bummed.

    I guess I've learned not to give up on an idea so easily...next time I get into one of these binds I won't waste 7 hours assuming my first idea was wrong because of the content, and not the context like it was.


    Thanks again, God I keep thinking about how I know there's no way I would have tried chdir(argv[1]) again if you hadn't suggested it.

    What a nightmare.


    Did I say thanks yet?


    - CHL

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem building Quake source
    By Silvercord in forum Game Programming
    Replies: 16
    Last Post: 07-11-2010, 09:13 AM
  2. No Version info tab in file properties?
    By cpjust in forum Windows Programming
    Replies: 2
    Last Post: 06-03-2008, 03:42 PM
  3. How to set File Version of VC++ 6 dll
    By mercury529 in forum Windows Programming
    Replies: 3
    Last Post: 12-08-2006, 02:49 PM