Implementing the ls -al command in C

£可爱£侵袭症+ 提交于 2019-12-20 17:40:57

问题


As a part of an assignment from one of my classes, I have to write a program in C to duplicate the results of the ls -al command. I have read up on the necessary materials but I am still not getting the right output. Here is my code so far, its only supposed to print out the file size and the file name, but the file sizes its printing are not correct.

Code:

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

int main(int argc, char* argv[])
{
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;

    mydir = opendir(argv[1]);
    while((myfile = readdir(mydir)) != NULL)
    {
        stat(myfile->d_name, &mystat);    
        printf("%d",mystat.st_size);
        printf(" %s\n", myfile->d_name);
    }
    closedir(mydir);
}

These are my results after executing the code:

[root@localhost ~]# ./a.out Downloads
4096 ..
4096 hw22.c
4096 ankur.txt
4096 .
4096 destination.txt

Here are the correct sizes:

[root@localhost ~]# ls -al Downloads
total 20
drwxr-xr-x.  2 root root 4096 Nov 26 01:35 .
dr-xr-x---. 24 root root 4096 Nov 26 01:29 ..
-rw-r--r--.  1 root root   27 Nov 21 06:32 ankur.txt
-rw-r--r--.  1 root root   38 Nov 21 06:50 destination.txt
-rw-r--r--.  1 root root 1139 Nov 25 23:38 hw22.c

Can anyone please point out my mistake.

Thanks,

Ankur


回答1:


myfile->d_name is the file name not the path, so you need to append the file name to the directory "Downloads/file.txt" first, if it's is not the working directory:

char buf[512];    
while((myfile = readdir(mydir)) != NULL)
{
    sprintf(buf, "%s/%s", argv[1], myfile->d_name);
    stat(buf, &mystat);
....

As to why it prints 4096 that is the size of the links . and .. from the last call to stat().

Note: you should allocate a buffer large enough to hold the directory name, the file name the NULL byte and the separator, something like this

strlen(argv[1]) + NAME_MAX + 2;



回答2:


This is the final code I got to work for anyone interested. It prints the correct file sizes. Credit goes to asker and mux for answering, just putting the code together. Input I got this to work for is "./main ." .

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

int main(int argc, char* argv[])
{
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;

    char buf[512];
    mydir = opendir(argv[1]);
    while((myfile = readdir(mydir)) != NULL)
    {
        sprintf(buf, "%s/%s", argv[1], myfile->d_name);
        stat(buf, &mystat);
        printf("%zu",mystat.st_size);
        printf(" %s\n", myfile->d_name);
    }
    closedir(mydir);
}



回答3:


I believe you'll observe that if you ./a.out . you will get the behaviour you expect.

You have a slightly subtle bug, observable if you examine the return code of your call to stat(2).

The fundamental mistake: the dirents returned by readdir(2) (the myfile in your code) will have a d_name relative to mydir. Your code will stat .. first, succeed, and so mystat will contain valid data for .., then all subsequent calls to stat(2) will fail, returning -1, which you do not check for, so mystat will not be modified, and you will print the st_size for the old value, i.e. that of ...




回答4:


The trouble is that when you stat("ankur.txt", &mystat), you are not working on the file "Downloads/ankur.txt". Most likely, the stat() is failing; alternatively, it is reporting on a different file.

Consequently, you need to look at whether your system supports fstatat() — new in POSIX 2008 — or arrange to prefix the name of the file with name of the directory.




回答5:


or maybe just system("ls -al") will also work!



来源:https://stackoverflow.com/questions/13554150/implementing-the-ls-al-command-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!