0

I'm trying to write a simple implementation of the ls command, close to ls -l, but not exactly the same.

Here's what I have so far

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <time.h>

using namespace std;
int main(int argc, char **argv)
{
    if(argc != 2)
    {
        cout << "Usage: ./Asg4 <directoryName>" << endl;
        return -1;
    }

    struct stat sb;
    DIR *d;
    struct dirent *dir;
    d = opendir(argv[1]);

    if(d)
    {
        while((dir = readdir(d)) != NULL)
        {
            stat(dir->d_name, &sb);
            printf("%ld\t %s\t%lo\t%ld\t%lld\t%s\n", sb.st_ino, sb.st_dev, (unsigned long) sb.st_mode, (long) sb.st_nlink, (long long) sb.st_size, ctime(&sb.st_mtime));
        }
        closedir(d);
    }
    return 0;
}

But when I execute it on any given directory, it gives me a segmentation fault. Any ideas?

In response to Loki Astari's answer, I changed the printf to

printf("%ld\t %d\t%lo\t%ld\t%lld\t%s\n", (long) sb.st_ino, (int) sb.st_dev, (unsigned long) sb.st_mode, (long) sb.st_nlink, (long long) sb.st_size, ctime(&sb.st_mtime));

which seems to have resolved the segmentation fault.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew Smith
  • 21
  • 1
  • 6
  • For one thing, you're not `stat`-ing the files you think you are. See these two previous questions: http://stackoverflow.com/questions/36867401/c-strange-stat-st-mode , http://stackoverflow.com/questions/5125919/stat-error-no-such-file-or-directory-when-file-name-is-returned-by-readdir – Steve Summit May 05 '16 at 23:38
  • See the answer from @LokiAstari about why your code is crashing. Also, you should definitely check `stat`'s return value. – Steve Summit May 05 '16 at 23:59

1 Answers1

2

When I compile I get some nasty warnings:

xc.cpp:28:54: warning: format specifies type 'long' but the argument has type '__darwin_ino64_t' (aka 'unsigned long long') [-Wformat]
            printf("%ld\t %s\t%lo\t%ld\t%lld\t%s\n", sb.st_ino, sb.st_dev, (unsigned long) sb.st_mode, (long) sb.st_nlink, (long long) sb.st_size, ctime(&sb.st_mtime));
                    ~~~                              ^~~~~~~~~
                    %llu
xc.cpp:28:65: warning: format specifies type 'char *' but the argument has type 'dev_t' (aka 'int') [-Wformat]
            printf("%ld\t %s\t%lo\t%ld\t%lld\t%s\n", sb.st_ino, sb.st_dev, (unsigned long) sb.st_mode, (long) sb.st_nlink, (long long) sb.st_size, ctime(&sb.st_mtime));
                          ~~                                    ^~~~~~~~~
                          %d

Those look like errors that would crash.
It also is a good advert for using C++ rather than C. The C++ streams don't have this issue.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Specifically, trying to print `st_dev` as a string, using `%s`, is just about guaranteed to crash. `st_dev` is a number, not a string. – Steve Summit May 05 '16 at 23:57
  • I edited my question with what I did, for some reason I wasn't getting those warnings. Thank you @Loki Astari! – Andrew Smith May 06 '16 at 00:05